diff --git a/ava.config.js b/ava.config.js index cca5314a8..a250498d6 100644 --- a/ava.config.js +++ b/ava.config.js @@ -1,19 +1,19 @@ export default { - "extensions": { - "ts": "module" + extensions: { + ts: "module", }, - "files": [ - "test/lib/**/*.ts" + files: [ + "test/lib/**/*.ts", ], - "watcher": { - "ignoreChanges": [ + watcher: { + ignoreChanges: [ "test/tmp/**", - "lib/**" - ] + "lib/**", + ], }, - "nodeArguments": [ + nodeArguments: [ "--import=tsx/esm", - "--no-warnings=ExperimentalWarning" + "--no-warnings=ExperimentalWarning", ], - "workerThreads": false + workerThreads: false, }; diff --git a/scripts/metadataProvider/MetadataProvider.ts b/scripts/metadataProvider/MetadataProvider.ts index 806aec843..bd4239439 100644 --- a/scripts/metadataProvider/MetadataProvider.ts +++ b/scripts/metadataProvider/MetadataProvider.ts @@ -1,7 +1,7 @@ import {createSemanticModel} from "./model.js"; import { - findSymbol + findSymbol, } from "@ui5-language-assistant/semantic-model"; import { BaseUI5Node, @@ -46,4 +46,3 @@ export default class MetadataProvider { return classMetadata.defaultAggregation?.name; } } - diff --git a/scripts/metadataProvider/createMetadataInfo.ts b/scripts/metadataProvider/createMetadataInfo.ts index d1bc08d5d..49a396f4d 100644 --- a/scripts/metadataProvider/createMetadataInfo.ts +++ b/scripts/metadataProvider/createMetadataInfo.ts @@ -2,7 +2,7 @@ import {writeFile} from "node:fs/promises"; import MetadataProvider from "./MetadataProvider"; import { - forEachSymbol + forEachSymbol, } from "@ui5-language-assistant/semantic-model"; async function main(apiJsonsRoot: string, sapui5Version: string) { @@ -22,9 +22,9 @@ async function main(apiJsonsRoot: string, sapui5Version: string) { const apiExtract = { framework: { name: "SAPUI5", - version: sapui5Version + version: sapui5Version, }, - defaultAggregations + defaultAggregations, }; await writeFile( diff --git a/scripts/metadataProvider/model.ts b/scripts/metadataProvider/model.ts index d7b96ac61..742bdac58 100644 --- a/scripts/metadataProvider/model.ts +++ b/scripts/metadataProvider/model.ts @@ -6,22 +6,22 @@ import { TypeNameFix, } from "@ui5-language-assistant/semantic-model"; import { - UI5SemanticModel + UI5SemanticModel, } from "@ui5-language-assistant/semantic-model-types"; interface ApiJson { - library: string + library: string; } function getTypeNameFix(): TypeNameFix { // From https://github.com/SAP/ui5-language-assistant/blob/44114f34de59e8d415b06b470be6fa3697c7414c/packages/context/src/ui5-model.ts#L229 const fixes: TypeNameFix = { - Control: "sap.ui.core.Control", - Element: "sap.ui.core.Element", - array: "object[]", - Array: "object[]", - bloolean: "boolean", - any: "any", + "Control": "sap.ui.core.Control", + "Element": "sap.ui.core.Element", + "array": "object[]", + "Array": "object[]", + "bloolean": "boolean", + "any": "any", "sap.m.PlanningCalendarHeader": undefined, "sap.m.TimePickerSlider": undefined, "sap.ui.layout.ResponsiveSplitterPage": undefined, diff --git a/src/cli.ts b/src/cli.ts index 05dafe657..5a2c1c7b0 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,21 +1,21 @@ import yargs from "yargs"; -import { hideBin } from "yargs/helpers"; +import {hideBin} from "yargs/helpers"; import base from "./cli/base.js"; -import { fileURLToPath } from "node:url"; -import { setVersion } from "./cli/version.js"; -import { createRequire } from "module"; +import {fileURLToPath} from "node:url"; +import {setVersion} from "./cli/version.js"; +import {createRequire} from "module"; export default async function () { const cli = yargs(hideBin(process.argv)); cli.parserConfiguration({ - "parse-numbers": false + "parse-numbers": false, }); // Explicitly set CLI version as the yargs default might // be wrong in case a local CLI installation is used // Also add CLI location const require = createRequire(import.meta.url); - const pkg = require("../package.json") as { version: string }; + const pkg = require("../package.json") as {version: string}; const ui5LintJsPath = fileURLToPath(new URL("../bin/ui5lint.js", import.meta.url)); const pkgVersion = `${pkg.version} (from ${ui5LintJsPath})`; diff --git a/src/cli/base.ts b/src/cli/base.ts index ba285e086..4e3b0e642 100644 --- a/src/cli/base.ts +++ b/src/cli/base.ts @@ -1,13 +1,13 @@ import {Argv, ArgumentsCamelCase} from "yargs"; import path from "node:path"; -import { lintProject } from "../linter/linter.js"; -import { Text } from "../formatter/text.js"; -import { Json } from "../formatter/json.js"; -import { Coverage } from "../formatter/coverage.js"; -import { writeFile } from "node:fs/promises"; +import {lintProject} from "../linter/linter.js"; +import {Text} from "../formatter/text.js"; +import {Json} from "../formatter/json.js"; +import {Coverage} from "../formatter/coverage.js"; +import {writeFile} from "node:fs/promises"; import baseMiddleware from "./middlewares/base.js"; import chalk from "chalk"; -import { isLogLevelEnabled } from "@ui5/logger"; +import {isLogLevelEnabled} from "@ui5/logger"; import ConsoleWriter from "@ui5/logger/writers/Console"; const lintCommand = { @@ -19,49 +19,49 @@ const lintCommand = { cli.usage("Usage: $0 [options]") .option("file-paths", { describe: "", - type: "string" + type: "string", }) .array("file-paths") .option("coverage", { describe: "Whether to provide a coverage report", - type: "boolean" + type: "boolean", }) .option("details", { describe: "Print complementary information for each finding, if available", - type: "boolean" + type: "boolean", }) .option("loglevel", { alias: "log-level", describe: "Set the logging level", default: "info", type: "string", - choices: ["silent", "error", "warn", "info", "perf", "verbose", "silly"] + choices: ["silent", "error", "warn", "info", "perf", "verbose", "silly"], }) .option("verbose", { describe: "Enable verbose logging.", default: false, - type: "boolean" + type: "boolean", }) .option("perf", { describe: "Enable performance measurements and related logging.", default: false, - type: "boolean" + type: "boolean", }) .option("silent", { describe: "Disable all log output.", default: false, - type: "boolean" + type: "boolean", }) .option("format", { alias: "f", describe: "Set the output format for the linter result", default: "stylish", type: "string", - choices: ["stylish", "json"] + choices: ["stylish", "json"], }) .coerce([ // base.js - "log-level" + "log-level", ], (arg) => { // If an option is specified multiple times, yargs creates an array for all the values, // independently of whether the option is of type "array" or "string". @@ -84,7 +84,7 @@ const lintCommand = { "Execute command with scope of file-paths"); return cli; - } + }, }; async function handleLint(argv: ArgumentsCamelCase) { @@ -92,8 +92,8 @@ async function handleLint(argv: ArgumentsCamelCase) { coverage, filePaths, details, - format - } = <{ coverage: boolean, filePaths: string[], details: boolean, format: string }>argv; + format, + } = (argv as unknown) as {coverage: boolean; filePaths: string[]; details: boolean; format: string}; let profile; if (process.env.UI5LINT_PROFILE) { @@ -114,7 +114,6 @@ async function handleLint(argv: ArgumentsCamelCase) { if (format === "json") { const jsonFormatter = new Json(); process.stdout.write(jsonFormatter.format(res, details)); - } else if (format === "" || format === "stylish") { const textFormatter = new Text(); process.stderr.write(textFormatter.format(res, details)); @@ -159,11 +158,11 @@ export default function base(cli: Argv) { chalk.dim( `If you think this is an issue of the ui5-linter, you might report it using the ` + `following URL: `) + - chalk.dim.bold.underline(`https://github.com/SAP/ui5-linter/issues/new/choose`)+"\n"); + chalk.dim.bold.underline(`https://github.com/SAP/ui5-linter/issues/new/choose`) + "\n"); } else { process.stderr.write("\n"); process.stderr.write(chalk.dim(`For details, execute the same command again with an` + - ` additional '--verbose' parameter`) + "\n"); + ` additional '--verbose' parameter`) + "\n"); } } } else { @@ -171,7 +170,7 @@ export default function base(cli: Argv) { process.stderr.write(chalk.bold.yellow("Command Failed:\n")); process.stderr.write(`${msg}\n`); process.stderr.write("\n"); - process.stderr.write(chalk.dim(`See 'ui5lint --help'`)+"\n"); + process.stderr.write(chalk.dim(`See 'ui5lint --help'`) + "\n"); } process.exit(1); }); diff --git a/src/cli/middlewares/base.ts b/src/cli/middlewares/base.ts index 0c48e62a4..b86276238 100644 --- a/src/cli/middlewares/base.ts +++ b/src/cli/middlewares/base.ts @@ -1,5 +1,5 @@ -import { initLogger } from "./logger.js"; -import type { ArgumentsCamelCase } from "yargs"; +import {initLogger} from "./logger.js"; +import type {ArgumentsCamelCase} from "yargs"; /** * Base middleware for CLI commands. * diff --git a/src/cli/middlewares/logger.ts b/src/cli/middlewares/logger.ts index 83bd2eb31..140c2750f 100644 --- a/src/cli/middlewares/logger.ts +++ b/src/cli/middlewares/logger.ts @@ -1,7 +1,7 @@ import {setLogLevel, isLogLevelEnabled, getLogger} from "@ui5/logger"; import ConsoleWriter from "@ui5/logger/writers/Console"; import {getVersion} from "../version.js"; -import type { ArgumentsCamelCase } from "yargs"; +import type {ArgumentsCamelCase} from "yargs"; /** * Logger middleware to enable logging capabilities * @@ -21,7 +21,7 @@ export async function initLogger(argv: ArgumentsCamelCase) { // argv.loglevel defaults to "info", which is anyways already the Logger's default // Therefore do not explicitly set it again in order to allow overwriting the log level // using the UI5_LOG_LVL environment variable - setLogLevel(argv.loglevel); + setLogLevel((argv.loglevel as string)); } // Initialize writer diff --git a/src/cli/utils/profile.ts b/src/cli/utils/profile.ts index 2e88e71bd..c99ec3930 100644 --- a/src/cli/utils/profile.ts +++ b/src/cli/utils/profile.ts @@ -4,7 +4,7 @@ import {getLogger} from "@ui5/logger"; const log = getLogger("cli:utils:profile"); let session: Session | null; -type ProcessSignals = Record void> +type ProcessSignals = Record void>; let processSignals: ProcessSignals | null; export async function start() { @@ -70,7 +70,7 @@ export async function stop() { function registerSigHooks() { function createListener(exitCode: number) { - return function() { + return function () { // Gracefully end profiling, then exit stop().then(() => { process.exit(exitCode); @@ -79,10 +79,10 @@ function registerSigHooks() { } const processSignals: ProcessSignals = { - "SIGHUP": createListener(128 + 1), - "SIGINT": createListener(128 + 2), - "SIGTERM": createListener(128 + 15), - "SIGBREAK": createListener(128 + 21) + SIGHUP: createListener(128 + 1), + SIGINT: createListener(128 + 2), + SIGTERM: createListener(128 + 15), + SIGBREAK: createListener(128 + 21), }; for (const signal of Object.keys(processSignals)) { diff --git a/src/detectors/AbstractDetector.ts b/src/detectors/AbstractDetector.ts index be7a13989..e95fd1de5 100644 --- a/src/detectors/AbstractDetector.ts +++ b/src/detectors/AbstractDetector.ts @@ -3,29 +3,29 @@ import {Project} from "@ui5/project"; // 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 export interface LintResult { - filePath: string, - messages: LintMessage[], - coverageInfo: CoverageInfo[], - errorCount: number, // includes fatal errors - fatalErrorCount: number, - warningCount: number, + filePath: string; + messages: LintMessage[]; + coverageInfo: CoverageInfo[]; + errorCount: number; // includes fatal errors + fatalErrorCount: number; + warningCount: number; } export enum LintMessageSeverity { Warning = 1, - Error = 2 + Error = 2, } export interface LintMessage { - ruleId: string, - severity: LintMessageSeverity, - message: string, - messageDetails?: string, - fatal?: boolean | undefined, // e.g. parsing error - line?: number | undefined, // 1 based to be aligned with most IDEs - column?: number | undefined, // 1 based to be aligned with most IDEs - endLine?: number | undefined, - endColumn?: number | undefined + ruleId: string; + severity: LintMessageSeverity; + message: string; + messageDetails?: string; + fatal?: boolean | undefined; // e.g. parsing error + line?: number | undefined; // 1 based to be aligned with most IDEs + column?: number | undefined; // 1 based to be aligned with most IDEs + endLine?: number | undefined; + endColumn?: number | undefined; } export enum CoverageCategory { @@ -33,13 +33,13 @@ export enum CoverageCategory { } export interface CoverageInfo { - category: CoverageCategory - message: string, - messageDetails?: string, - line?: number | undefined, // 1 based to be aligned with most IDEs - column?: number | undefined, // 1 based to be aligned with most IDEs - endLine?: number | undefined, - endColumn?: number | undefined + category: CoverageCategory; + message: string; + messageDetails?: string; + line?: number | undefined; // 1 based to be aligned with most IDEs + column?: number | undefined; // 1 based to be aligned with most IDEs + endLine?: number | undefined; + endColumn?: number | undefined; } // export interface DetectorCapabilities { @@ -47,10 +47,10 @@ export interface CoverageInfo { // } abstract class AbstractDetector { - abstract createReports(filePaths: string[]): Promise + abstract createReports(filePaths: string[]): Promise; // abstract getCapabilities(): DetectorCapabilities } -export abstract class FileBasedDetector extends AbstractDetector{ +export abstract class FileBasedDetector extends AbstractDetector { rootDir: string; constructor(rootDir: string) { @@ -59,7 +59,7 @@ export abstract class FileBasedDetector extends AbstractDetector{ } } -export abstract class ProjectBasedDetector extends AbstractDetector{ +export abstract class ProjectBasedDetector extends AbstractDetector { project: Project; constructor(project: Project) { diff --git a/src/detectors/BaseReporter.ts b/src/detectors/BaseReporter.ts index 966b5b321..77f3173a0 100644 --- a/src/detectors/BaseReporter.ts +++ b/src/detectors/BaseReporter.ts @@ -1,34 +1,34 @@ import type ts from "typescript"; -import type { LintMessage, CoverageInfo, LintResult } from "../detectors/AbstractDetector.js"; +import type {LintMessage, CoverageInfo, LintResult} from "../detectors/AbstractDetector.js"; export interface BaseReporter { - addMessage(args: ReporterMessage): void, - addCoverageInfo(args: ReporterCoverageInfo): void, - getReport(): LintResult + addMessage(args: ReporterMessage): void; + addCoverageInfo(args: ReporterCoverageInfo): void; + getReport(): LintResult; } -export type ReporterMessage = { - node?: ts.Node | string, - message: LintMessage["message"], - messageDetails?: LintMessage["messageDetails"], - severity: LintMessage["severity"], - ruleId: LintMessage["ruleId"], - fatal?: LintMessage["fatal"], +export interface ReporterMessage { + node?: ts.Node | string; + message: LintMessage["message"]; + messageDetails?: LintMessage["messageDetails"]; + severity: LintMessage["severity"]; + ruleId: LintMessage["ruleId"]; + fatal?: LintMessage["fatal"]; } export interface PositionInfo { - line: number, - column: number, + line: number; + column: number; } export interface PositionRange { - start: PositionInfo - end?: PositionInfo + start: PositionInfo; + end?: PositionInfo; } export interface ReporterCoverageInfo { - node: ts.Node | string, - message: CoverageInfo["message"], - messageDetails?: CoverageInfo["messageDetails"], - category: CoverageInfo["category"], + node: ts.Node | string; + message: CoverageInfo["message"]; + messageDetails?: CoverageInfo["messageDetails"]; + category: CoverageInfo["category"]; } diff --git a/src/detectors/Reporter.ts b/src/detectors/Reporter.ts index 469ad8927..e2b62263c 100644 --- a/src/detectors/Reporter.ts +++ b/src/detectors/Reporter.ts @@ -4,7 +4,7 @@ import { TraceMap, originalPositionFor, LEAST_UPPER_BOUND, - GREATEST_LOWER_BOUND + GREATEST_LOWER_BOUND, } from "@jridgewell/trace-mapping"; import {LintMessageSeverity} from "./AbstractDetector.js"; @@ -16,7 +16,7 @@ import type { ReporterMessage, ReporterCoverageInfo, PositionInfo, - PositionRange + PositionRange, } from "./BaseReporter.js"; export default class Reporter implements BaseReporter { @@ -43,14 +43,14 @@ export default class Reporter implements BaseReporter { let line = 1, column = 1; if (node) { - const {start} = this.#getPositionsForNode(node); + const {start} = this.#getPositionsForNode((node as ts.Node)); // One-based to be aligned with most IDEs line = start.line + 1; column = start.column + 1; // endLine = end.line + 1; // endColumn = end.column + 1; } - + const msg: LintMessage = { ruleId, severity, @@ -59,16 +59,16 @@ export default class Reporter implements BaseReporter { column, message, }; - + if (messageDetails) { - msg["messageDetails"] = resolveLinks(messageDetails); + msg.messageDetails = resolveLinks(messageDetails); } this.#messages.push(msg); } addCoverageInfo({node, message, messageDetails, category}: ReporterCoverageInfo) { - const {start} = this.#getPositionsForNode(node); + const {start} = this.#getPositionsForNode((node as ts.Node)); const coverageInfo: CoverageInfo = { category, // One-based to be aligned with most IDEs @@ -76,13 +76,13 @@ export default class Reporter implements BaseReporter { column: start.column + 1, // endLine: end.line + 1, // endColumn: end.column + 1, - message + message, }; - + if (messageDetails) { - coverageInfo["messageDetails"] = resolveLinks(messageDetails); + coverageInfo.messageDetails = resolveLinks(messageDetails); } - + this.#coverageInfo.push(coverageInfo); } @@ -105,7 +105,7 @@ export default class Reporter implements BaseReporter { let tracedPos = originalPositionFor(this.#traceMap, { line: line + 1, column, - bias: GREATEST_LOWER_BOUND + bias: GREATEST_LOWER_BOUND, }); if (tracedPos.line === null) { @@ -114,7 +114,7 @@ export default class Reporter implements BaseReporter { tracedPos = originalPositionFor(this.#traceMap, { line: line + 1, column, - bias: LEAST_UPPER_BOUND + bias: LEAST_UPPER_BOUND, }); } @@ -125,12 +125,12 @@ export default class Reporter implements BaseReporter { } return { line: tracedPos.line - 1, // Subtract 1 again to restore zero-based lines to match TypeScript output - column: tracedPos.column + column: tracedPos.column, }; } return { line, - column + column, }; } diff --git a/src/detectors/transpilers/AbstractTranspiler.ts b/src/detectors/transpilers/AbstractTranspiler.ts index 3a108ddde..179df8e35 100644 --- a/src/detectors/transpilers/AbstractTranspiler.ts +++ b/src/detectors/transpilers/AbstractTranspiler.ts @@ -1,7 +1,7 @@ import {LintMessage} from "../AbstractDetector.js"; export interface TranspileResult { - source: string, - map: string, - messages?: LintMessage[], + source: string; + map: string; + messages?: LintMessage[]; } diff --git a/src/detectors/transpilers/amd/TsTransformer.ts b/src/detectors/transpilers/amd/TsTransformer.ts index 5f7843329..6fc9191d1 100644 --- a/src/detectors/transpilers/amd/TsTransformer.ts +++ b/src/detectors/transpilers/amd/TsTransformer.ts @@ -13,7 +13,7 @@ const log = getLogger("transpilers:amd:TsTransformer"); // Augment typescript's Node interface to add a property for marking nodes for removal declare module "typescript" { interface Node { - _remove?: boolean + _remove?: boolean; } } @@ -66,7 +66,7 @@ function transform( const moduleDefinition = moduleDeclarationToDefinition(moduleDeclaration, sourceFile, nodeFactory); moduleDefinitions.push(moduleDefinition); pruneNode(node); // Mark the define call for removal - } catch(err) { + } catch (err) { if (err instanceof UnsupportedModuleError) { log.verbose(`Failed to transform sap.ui.define call in ${resourcePath}: ${err.message}`); } else { @@ -88,7 +88,7 @@ function transform( // async sap.ui.require without a callback (import only) try { pruneNode(node); - } catch(err) { + } catch (err) { if (err instanceof UnsafeNodeRemoval) { // If removal is not possible, replace the CallExpression with "undefined" // (i.e. the original return value) @@ -103,7 +103,7 @@ function transform( requireImports.push(res.import); replaceNode(node, res.requireStatement); } - } catch(err) { + } catch (err) { if (err instanceof UnsupportedModuleError) { log.verbose(`Failed to transform sap.ui.require call in ${resourcePath}: ${err.message}`); } else { @@ -152,7 +152,7 @@ function transform( // TODO PERF: Use a match array instead of string to be able to match individual parts of the property access chain // early (i.e. exist immediately if the last expression does not match the last match) -function matchPropertyAccessExpression(node: ts.PropertyAccessExpression, match: string) : boolean { +function matchPropertyAccessExpression(node: ts.PropertyAccessExpression, match: string): boolean { const propAccessChain: string[] = []; propAccessChain.push(node.expression.getText()); diff --git a/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts b/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts index 15d7b1586..bd8f7e88f 100644 --- a/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts +++ b/src/detectors/transpilers/amd/moduleDeclarationToDefinition.ts @@ -9,12 +9,12 @@ const {SyntaxKind} = ts; const log = getLogger("transpilers:amd:moduleDeclarationToDefinition"); export interface ModuleDefinition { - name?: string, - body: ts.Statement[], - imports: ts.ImportDeclaration[] + name?: string; + body: ts.Statement[]; + imports: ts.ImportDeclaration[]; } -export default function( +export default function ( moduleDeclaration: ModuleDeclaration, sourceFile: ts.SourceFile, nodeFactory: ts.NodeFactory ): ModuleDefinition { const {imports, identifiers: importIdentifiers} = collectImports(moduleDeclaration, nodeFactory); @@ -35,8 +35,8 @@ export default function( */ function collectImports( moduleDeclaration: ModuleDeclaration, - nodeFactory: ts.NodeFactory, -): {imports: ts.ImportDeclaration[], identifiers: ts.Identifier[]} { + nodeFactory: ts.NodeFactory +): {imports: ts.ImportDeclaration[]; identifiers: ts.Identifier[]} { const imports: ts.ImportDeclaration[] = []; const identifiers: ts.Identifier[] = []; if (!moduleDeclaration.dependencies) { @@ -76,14 +76,14 @@ function collectImports( let moduleSpecifier: ts.StringLiteral; if (!ts.isStringLiteralLike(dep)) { log.verbose(`Skipping non-string dependency entry of type ${ts.SyntaxKind[dep.kind]} at ` + - toPosStr(dep)); + toPosStr(dep)); return; } if (ts.isNoSubstitutionTemplateLiteral(dep)) { moduleSpecifier = nodeFactory.createStringLiteral(dep.text); // Set pos to the original position to preserve source mapping capability // (cast type to avoid TS error due to modifying a read only property) - (moduleSpecifier.pos as ts.Node["pos"]) = dep.pos; + (moduleSpecifier.pos) = dep.pos; } else { moduleSpecifier = dep; } @@ -92,7 +92,7 @@ function collectImports( // Generate variable name based on import module // Later this variable will be used to call the factory function identifier = nodeFactory.createUniqueName(dep.text.replace(/[^a-zA-Z0-9]/g, "_")); - } else if (factoryParams && factoryParams[i]) { + } else if (factoryParams?.[i]) { // Use factory parameter identifier as import identifier identifier = factoryParams[i]; } // else: Side effect imports. No identifier needed @@ -129,7 +129,7 @@ function getModuleBody( moduleDeclaration: ModuleDeclaration, sourceFile: ts.SourceFile, nodeFactory: ts.NodeFactory, - importIdentifiers: ts.Identifier[], + importIdentifiers: ts.Identifier[] ): ts.Statement[] { if (!moduleDeclaration.factory) { return []; @@ -138,7 +138,6 @@ function getModuleBody( if ((ts.isFunctionExpression(moduleDeclaration.factory) || ts.isArrowFunction(moduleDeclaration.factory) || ts.isFunctionDeclaration(moduleDeclaration.factory))) { - if (!moduleDeclaration.factory.body) { // Empty function body, no export body = []; @@ -180,10 +179,10 @@ function getModuleBody( const classDeclaration = rewriteExtendCall(nodeFactory, node.expression, [ nodeFactory.createToken(ts.SyntaxKind.ExportKeyword), - nodeFactory.createToken(ts.SyntaxKind.DefaultKeyword) + nodeFactory.createToken(ts.SyntaxKind.DefaultKeyword), ]); body.push(classDeclaration); - } catch(err) { + } catch (err) { if (err instanceof UnsupportedExtendCall) { log.verbose(`Failed to transform extend call: ${err.message}`); body.push(createDefaultExport(nodeFactory, node.expression)); @@ -197,7 +196,7 @@ function getModuleBody( // node.expression)); } } else if (ts.isExpressionStatement(node) && ts.isStringLiteral(node.expression) && - node.expression.text === "use strict") { + node.expression.text === "use strict") { // Ignore "use strict" directive continue; } else { @@ -213,10 +212,10 @@ function getModuleBody( const classDeclaration = rewriteExtendCall(nodeFactory, moduleDeclaration.factory.body, [ nodeFactory.createToken(ts.SyntaxKind.ExportKeyword), - nodeFactory.createToken(ts.SyntaxKind.DefaultKeyword) + nodeFactory.createToken(ts.SyntaxKind.DefaultKeyword), ]); body = [classDeclaration]; - } catch(err) { + } catch (err) { if (err instanceof UnsupportedExtendCall) { log.verbose(`Failed to transform extend call: ${err.message}`); body = [createDefaultExport(nodeFactory, moduleDeclaration.factory.body)]; @@ -229,10 +228,10 @@ function getModuleBody( body = [createDefaultExport(nodeFactory, moduleDeclaration.factory.body)]; } } else if (ts.isClassDeclaration(moduleDeclaration.factory) || - ts.isLiteralExpression(moduleDeclaration.factory) || - ts.isArrayLiteralExpression(moduleDeclaration.factory) || - ts.isObjectLiteralExpression(moduleDeclaration.factory) || - ts.isPropertyAccessExpression(moduleDeclaration.factory)) { + ts.isLiteralExpression(moduleDeclaration.factory) || + ts.isArrayLiteralExpression(moduleDeclaration.factory) || + ts.isObjectLiteralExpression(moduleDeclaration.factory) || + ts.isPropertyAccessExpression(moduleDeclaration.factory)) { // Use factory directly body = [createDefaultExport(nodeFactory, moduleDeclaration.factory)]; } else { // Identifier @@ -248,21 +247,21 @@ function getModuleBody( function collectReturnStatementsInScope(node: ts.Node, maxCount?: number): ts.ReturnStatement[] { const returnStatements: ts.ReturnStatement[] = []; function visitNode(node: ts.Node) { - switch(node.kind) { - case SyntaxKind.ReturnStatement: - returnStatements.push(node as ts.ReturnStatement); - return; + switch (node.kind) { + case SyntaxKind.ReturnStatement: + returnStatements.push(node as ts.ReturnStatement); + return; - // Do not traverse into nodes that declare a new function scope - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.Constructor: - case SyntaxKind.SetAccessor: - case SyntaxKind.GetAccessor: - return; + // Do not traverse into nodes that declare a new function scope + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessor: + return; } if (maxCount && returnStatements.length >= maxCount) { return; @@ -281,45 +280,45 @@ function createDefaultExport(factory: ts.NodeFactory, node: ts.Node): ts.Stateme } const exportModifiers = [ factory.createToken(ts.SyntaxKind.ExportKeyword), - factory.createToken(ts.SyntaxKind.DefaultKeyword) + factory.createToken(ts.SyntaxKind.DefaultKeyword), ]; - switch(node.kind) { - case SyntaxKind.CallExpression: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.Identifier: - case SyntaxKind.PropertyAccessExpression: - return factory.createExportAssignment(undefined, undefined, node as ts.Expression); - case SyntaxKind.ClassDeclaration: - return factory.updateClassDeclaration( - (node as ts.ClassDeclaration), - exportModifiers, - (node as ts.ClassDeclaration).name, - (node as ts.ClassDeclaration).typeParameters, - (node as ts.ClassDeclaration).heritageClauses, - (node as ts.ClassDeclaration).members); - case SyntaxKind.FunctionDeclaration: - return factory.updateFunctionDeclaration( - (node as ts.FunctionDeclaration), - exportModifiers, - (node as ts.FunctionDeclaration).asteriskToken, - (node as ts.FunctionDeclaration).name, - (node as ts.FunctionDeclaration).typeParameters, - (node as ts.FunctionDeclaration).parameters, - (node as ts.FunctionDeclaration).type, - (node as ts.FunctionDeclaration).body); - case SyntaxKind.FunctionExpression: - return factory.createFunctionDeclaration( - exportModifiers, - (node as ts.FunctionExpression).asteriskToken, - (node as ts.FunctionExpression).name, - (node as ts.FunctionExpression).typeParameters, - (node as ts.FunctionExpression).parameters, - (node as ts.FunctionExpression).type, - (node as ts.FunctionExpression).body); - default: - throw new UnsupportedModuleError( + switch (node.kind) { + case SyntaxKind.CallExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + return factory.createExportAssignment(undefined, undefined, node as ts.Expression); + case SyntaxKind.ClassDeclaration: + return factory.updateClassDeclaration( + (node as ts.ClassDeclaration), + exportModifiers, + (node as ts.ClassDeclaration).name, + (node as ts.ClassDeclaration).typeParameters, + (node as ts.ClassDeclaration).heritageClauses, + (node as ts.ClassDeclaration).members); + case SyntaxKind.FunctionDeclaration: + return factory.updateFunctionDeclaration( + (node as ts.FunctionDeclaration), + exportModifiers, + (node as ts.FunctionDeclaration).asteriskToken, + (node as ts.FunctionDeclaration).name, + (node as ts.FunctionDeclaration).typeParameters, + (node as ts.FunctionDeclaration).parameters, + (node as ts.FunctionDeclaration).type, + (node as ts.FunctionDeclaration).body); + case SyntaxKind.FunctionExpression: + return factory.createFunctionDeclaration( + exportModifiers, + (node as ts.FunctionExpression).asteriskToken, + (node as ts.FunctionExpression).name, + (node as ts.FunctionExpression).typeParameters, + (node as ts.FunctionExpression).parameters, + (node as ts.FunctionExpression).type, + (node as ts.FunctionExpression).body); + default: + throw new UnsupportedModuleError( `Unable to create default export assignment for node of type ${SyntaxKind[node.kind]} at ` + toPosStr(node)); } diff --git a/src/detectors/transpilers/amd/parseModuleDeclaration.ts b/src/detectors/transpilers/amd/parseModuleDeclaration.ts index d9be77db1..0ccf2d662 100644 --- a/src/detectors/transpilers/amd/parseModuleDeclaration.ts +++ b/src/detectors/transpilers/amd/parseModuleDeclaration.ts @@ -6,10 +6,10 @@ const log = getLogger("transpilers:amd:parseModuleDeclaration"); const {SyntaxKind} = ts; export interface ModuleDeclaration { - moduleName?: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral, - dependencies?: ts.ArrayLiteralExpression, - factory: DefineCallArgument, - export?: ts.BooleanLiteral, + moduleName?: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral; + dependencies?: ts.ArrayLiteralExpression; + factory: DefineCallArgument; + export?: ts.BooleanLiteral; } /** @@ -77,30 +77,30 @@ export default function parseModuleDeclaration( } // Keep this type in sync with the "assertSupportedTypes" function -export type DefineCallArgument = ts.StringLiteral |ts.NoSubstitutionTemplateLiteral | ts.NumericLiteral | +export type DefineCallArgument = ts.StringLiteral | ts.NoSubstitutionTemplateLiteral | ts.NumericLiteral | ts.ArrayLiteralExpression | ts.BooleanLiteral | ts.PropertyAccessExpression | ts.ObjectLiteralExpression | ts.ArrowFunction | ts.FunctionExpression | - ts.FunctionDeclaration | ts.ClassDeclaration | ts.NoSubstitutionTemplateLiteral; + ts.FunctionDeclaration | ts.ClassDeclaration; function assertSupportedTypes(args: (ts.Expression | ts.Declaration)[]): DefineCallArgument[] { args.forEach((arg, idx) => { // We only support a certain set of types. Abort if we encounter anything else switch (arg.kind) { - case SyntaxKind.StringLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionExpression: - case SyntaxKind.TrueKeyword: - case SyntaxKind.FalseKeyword: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.PropertyAccessExpression: - return; - default: - throw new UnsupportedModuleError( + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.PropertyAccessExpression: + return; + default: + throw new UnsupportedModuleError( `Unsupported type for argument in sap.ui.define call at index ${idx}: ${SyntaxKind[arg.kind]}`); } }); @@ -108,10 +108,10 @@ function assertSupportedTypes(args: (ts.Expression | ts.Declaration)[]): DefineC } const enum Param { - ModuleName = 0, + ModuleName = 0, Dependencies = 1, - Factory = 2, - Export = 3, + Factory = 2, + Export = 3, } export function _matchArgumentsToParameters(args: DefineCallArgument[]): ModuleDeclaration { @@ -188,7 +188,7 @@ export function _matchArgumentsToParameters(args: DefineCallArgument[]): ModuleD } else if (j === Param.Dependencies) { result.dependencies = args[i] as ModuleDeclaration["dependencies"]; } else if (j === Param.Factory) { - result.factory = args[i] as ModuleDeclaration["factory"]; + result.factory = args[i]; } else if (j === Param.Export) { result.export = args[i] as ModuleDeclaration["export"]; } @@ -210,11 +210,11 @@ function permute(arg: DefineCallArgument, startAt: Param): number[] { if (startAt <= Param.Dependencies && canBeDependencies(arg)) { perm[1] = 1; } - if(startAt <= Param.Factory && canBeFactory(arg)) { + if (startAt <= Param.Factory && canBeFactory(arg)) { perm[2] = 1; } - if(startAt <= Param.Export && canBeExport(arg)) { + if (startAt <= Param.Export && canBeExport(arg)) { perm[3] = 1; } return perm; diff --git a/src/detectors/transpilers/amd/parseRequire.ts b/src/detectors/transpilers/amd/parseRequire.ts index 2f2f1e768..2eb5707ee 100644 --- a/src/detectors/transpilers/amd/parseRequire.ts +++ b/src/detectors/transpilers/amd/parseRequire.ts @@ -6,14 +6,14 @@ const log = getLogger("amd:parseRequire"); const {SyntaxKind} = ts; export interface ProbingRequireExpression { - async: false, - dependency: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral, + async: false; + dependency: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral; } export interface RequireExpression { - async: true, - dependencies: ts.ArrayLiteralExpression, - callback?: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration, - errback?: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration + async: true; + dependencies: ts.ArrayLiteralExpression; + callback?: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration; + errback?: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration; } /** @@ -51,7 +51,7 @@ export default function parseRequire( if (ts.isIdentifier(arg)) { // Try and resolve the identifier to a more concrete node const sym = checker.getSymbolAtLocation(arg); - if (sym && sym.declarations) { + if (sym?.declarations) { for (const decl of sym.declarations) { if (ts.isVariableDeclaration(decl)) { if (decl.initializer) { @@ -95,21 +95,21 @@ function assertSupportedTypes(args: (ts.Expression | ts.Declaration)[]): Require args.forEach((arg, idx) => { // We only support a certain set of types. Abort if we encounter anything else switch (arg.kind) { - case SyntaxKind.StringLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionExpression: - case SyntaxKind.TrueKeyword: - case SyntaxKind.FalseKeyword: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.PropertyAccessExpression: - return; - default: - throw new UnsupportedModuleError( + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.PropertyAccessExpression: + return; + default: + throw new UnsupportedModuleError( `Unsupported type for argument in sap.ui.define call at index ${idx}: ${SyntaxKind[arg.kind]}`); } }); diff --git a/src/detectors/transpilers/amd/pruneNode.ts b/src/detectors/transpilers/amd/pruneNode.ts index eadc6b80b..efef3196d 100644 --- a/src/detectors/transpilers/amd/pruneNode.ts +++ b/src/detectors/transpilers/amd/pruneNode.ts @@ -19,7 +19,7 @@ export class UnsafeNodeRemoval extends Error { * * This is checked recursively for all parents */ -export default function(node: ts.Node) { +export default function (node: ts.Node) { let nodeToRemove: ts.Node | undefined = node; try { while (nodeToRemove) { @@ -30,7 +30,7 @@ export default function(node: ts.Node) { nodeToRemove = undefined; } } - } catch(err) { + } catch (err) { if ((err instanceof UnsafeNodeRemoval || err instanceof UnsupportedModuleError) && node !== nodeToRemove) { // Ignore UnsafeNodeRemoval and UnsupportedModuleError exceptions produced by parent nodes @@ -56,7 +56,7 @@ function pruneNode(node: ts.Node): boolean { log.verbose(`Parent node ${SyntaxKind[parent.kind]} can be removed`); return true; } - } catch(err) { + } catch (err) { if (err instanceof UnsafeNodeRemoval || err instanceof UnsupportedModuleError) { // If an UnsafeNodeRemoval or UnsupporedModuleError is detected, revert the removal of the node as // this would indicate that the parent can't exist without it @@ -79,75 +79,75 @@ function pruneNode(node: ts.Node): boolean { * nodes after removing their children will cause errors during later AST processing */ function isNodeRemovable(node: ts.Node): boolean { - switch(node.kind) { - case SyntaxKind.SourceFile: + switch (node.kind) { + case SyntaxKind.SourceFile: // Never remove the source file - return false; - - // Nodes with only one child - case SyntaxKind.Identifier: - case SyntaxKind.ExpressionStatement: - case SyntaxKind.VariableDeclaration: - case SyntaxKind.VariableStatement: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.ReturnStatement: - case SyntaxKind.AwaitExpression: - case SyntaxKind.ComputedPropertyName: - case SyntaxKind.Parameter: - case SyntaxKind.PrefixUnaryExpression: - case SyntaxKind.PostfixUnaryExpression: + return false; + + // Nodes with only one child + case SyntaxKind.Identifier: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.ReturnStatement: + case SyntaxKind.AwaitExpression: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.Parameter: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: // These nodes can only have one child // So if the child is removed, the parent must be removed as well - return true; - - // Nodes with multiple children - case SyntaxKind.FunctionExpression: - return isRemovableFunctionExpression(node as ts.FunctionExpression); - case SyntaxKind.MethodDeclaration: - return isRemovableMethodDeclaration(node as ts.MethodDeclaration); - case SyntaxKind.NewExpression: - return isRemovableNewExpression(node as ts.NewExpression); - case SyntaxKind.ArrowFunction: - return isRemovableArrowFunction(node as ts.ArrowFunction); - case SyntaxKind.IfStatement: - return isRemovableIfStatement(node as ts.IfStatement); - case SyntaxKind.BinaryExpression: - return isRemovableBinaryExpression(node as ts.BinaryExpression); - case SyntaxKind.ConditionalExpression: - return isRemovableConditionalExpression(node as ts.ConditionalExpression); - case SyntaxKind.ForStatement: - return isRemovableForStatement(node as ts.ForStatement); - case SyntaxKind.WhileStatement: - return isRemovableWhileStatement(node as ts.WhileStatement); - case SyntaxKind.DoStatement: - return isRemovableDoStatement(node as ts.DoStatement); - case SyntaxKind.PropertyAccessExpression: - return isRemovablePropertyAccessExpression(node as ts.PropertyAccessExpression); - case SyntaxKind.ElementAccessExpression: - return isRemovableElementAccessExpression(node as ts.ElementAccessExpression); - case SyntaxKind.FunctionDeclaration: - return isRemovableFunctionDeclaration(node as ts.FunctionDeclaration); - case SyntaxKind.PropertyAssignment: - return isRemovablePropertyAssignment(node as ts.PropertyAssignment); - case SyntaxKind.PropertyDeclaration: - return isRemovablePropertyDeclaration(node as ts.PropertyDeclaration); - case SyntaxKind.YieldExpression: - return isRemovableYieldExpression(node as ts.YieldExpression); - case SyntaxKind.ArrayLiteralExpression: - return isRemovableArrayLiteralExpression(node as ts.ArrayLiteralExpression); + return true; - case SyntaxKind.VariableDeclarationList: - return isRemovableVariableDeclarationList(node as ts.VariableDeclarationList); - case SyntaxKind.Block: - return isRemovableBlock(node as ts.Block); - case SyntaxKind.ObjectLiteralExpression: - return isRemovableObjectLiteralExpression(node as ts.ObjectLiteralExpression); - case SyntaxKind.CallExpression: - return isRemovableCallExpression(node as ts.CallExpression); - case SyntaxKind.ClassDeclaration: - return isRemovableClassDeclaration(node as ts.ClassDeclaration); - default: - throw new UnsupportedModuleError( + // Nodes with multiple children + case SyntaxKind.FunctionExpression: + return isRemovableFunctionExpression(node as ts.FunctionExpression); + case SyntaxKind.MethodDeclaration: + return isRemovableMethodDeclaration(node as ts.MethodDeclaration); + case SyntaxKind.NewExpression: + return isRemovableNewExpression(node as ts.NewExpression); + case SyntaxKind.ArrowFunction: + return isRemovableArrowFunction(node as ts.ArrowFunction); + case SyntaxKind.IfStatement: + return isRemovableIfStatement(node as ts.IfStatement); + case SyntaxKind.BinaryExpression: + return isRemovableBinaryExpression(node as ts.BinaryExpression); + case SyntaxKind.ConditionalExpression: + return isRemovableConditionalExpression(node as ts.ConditionalExpression); + case SyntaxKind.ForStatement: + return isRemovableForStatement(node as ts.ForStatement); + case SyntaxKind.WhileStatement: + return isRemovableWhileStatement(node as ts.WhileStatement); + case SyntaxKind.DoStatement: + return isRemovableDoStatement(node as ts.DoStatement); + case SyntaxKind.PropertyAccessExpression: + return isRemovablePropertyAccessExpression(node as ts.PropertyAccessExpression); + case SyntaxKind.ElementAccessExpression: + return isRemovableElementAccessExpression(node as ts.ElementAccessExpression); + case SyntaxKind.FunctionDeclaration: + return isRemovableFunctionDeclaration(node as ts.FunctionDeclaration); + case SyntaxKind.PropertyAssignment: + return isRemovablePropertyAssignment(node as ts.PropertyAssignment); + case SyntaxKind.PropertyDeclaration: + return isRemovablePropertyDeclaration(node as ts.PropertyDeclaration); + case SyntaxKind.YieldExpression: + return isRemovableYieldExpression(node as ts.YieldExpression); + case SyntaxKind.ArrayLiteralExpression: + return isRemovableArrayLiteralExpression(node as ts.ArrayLiteralExpression); + + case SyntaxKind.VariableDeclarationList: + return isRemovableVariableDeclarationList(node as ts.VariableDeclarationList); + case SyntaxKind.Block: + return isRemovableBlock(node as ts.Block); + case SyntaxKind.ObjectLiteralExpression: + return isRemovableObjectLiteralExpression(node as ts.ObjectLiteralExpression); + case SyntaxKind.CallExpression: + return isRemovableCallExpression(node as ts.CallExpression); + case SyntaxKind.ClassDeclaration: + return isRemovableClassDeclaration(node as ts.ClassDeclaration); + default: + throw new UnsupportedModuleError( `Unsupported parent node type for prune operation: ${SyntaxKind[node.kind]} at ` + `${toPosStr(node)}`); } @@ -174,7 +174,7 @@ function isRemovableMethodDeclaration(node: ts.MethodDeclaration): boolean { } function isRemovableNewExpression(node: ts.NewExpression): boolean { - return !!node.expression._remove && (!node.arguments|| hasAllNodesMarkedForRemoval(node.arguments)); + return !!node.expression._remove && (!node.arguments || hasAllNodesMarkedForRemoval(node.arguments)); } function isRemovableArrowFunction(node: ts.ArrowFunction): boolean { @@ -191,7 +191,7 @@ function isRemovableIfStatement(node: ts.IfStatement): boolean { function isRemovableBinaryExpression(node: ts.BinaryExpression): boolean { // Both sides of the binary expression are marked for removal => Remove the whole expression - if(node.left._remove && node.right._remove) { + if (node.left._remove && node.right._remove) { return true; } throw new UnsafeNodeRemoval( @@ -241,7 +241,6 @@ function isRemovableDoStatement( function isRemovablePropertyAccessExpression( node: ts.PropertyAccessExpression ): boolean { - if (node.name._remove && node.expression._remove) { return true; } diff --git a/src/detectors/transpilers/amd/replaceNodeInParent.ts b/src/detectors/transpilers/amd/replaceNodeInParent.ts index f1547d6fd..17d6043f9 100644 --- a/src/detectors/transpilers/amd/replaceNodeInParent.ts +++ b/src/detectors/transpilers/amd/replaceNodeInParent.ts @@ -5,14 +5,14 @@ import {toPosStr, UnsupportedModuleError} from "./util.js"; const log = getLogger("transpilers:amd:replaceNodeInParent"); export interface NodeReplacement { - original: ts.Node, - substitute: ts.Node, + original: ts.Node; + substitute: ts.Node; } /** * Replaces a node in its parent with another node */ -export default function( +export default function ( parent: ts.Node, replacement: NodeReplacement, nodeFactory: ts.NodeFactory ): ts.Node { const {original, substitute} = replacement; @@ -21,75 +21,75 @@ export default function( ` Old: ${ts.SyntaxKind[original.kind]}\n` + ` New: ${ts.SyntaxKind[substitute.kind]}`); - switch(parent.kind) { - case SyntaxKind.ExpressionStatement: - return replaceInExpressionStatement(parent as ts.ExpressionStatement, replacement, nodeFactory); - case SyntaxKind.ParenthesizedExpression: - return replaceInParenthesizedExpression(parent as ts.ParenthesizedExpression, replacement, nodeFactory); - case SyntaxKind.CallExpression: - return replaceInCallExpression(parent as ts.CallExpression, replacement, nodeFactory); - case SyntaxKind.NewExpression: - return replaceInNewExpression(parent as ts.NewExpression, replacement, nodeFactory); - case SyntaxKind.BinaryExpression: - return replaceInBinaryExpression(parent as ts.BinaryExpression, replacement, nodeFactory); - case SyntaxKind.ConditionalExpression: - return replaceInConditionalExpression(parent as ts.ConditionalExpression, replacement, nodeFactory); - case SyntaxKind.PrefixUnaryExpression: - return replaceInPrefixUnaryExpression(parent as ts.PrefixUnaryExpression, replacement, nodeFactory); - case SyntaxKind.PostfixUnaryExpression: - return replaceInPostfixUnaryExpression(parent as ts.PostfixUnaryExpression, replacement, nodeFactory); - case SyntaxKind.YieldExpression: - return replaceInYieldExpression(parent as ts.YieldExpression, replacement, nodeFactory); - case SyntaxKind.AwaitExpression: - return replaceInAwaitExpression(parent as ts.AwaitExpression, replacement, nodeFactory); - case SyntaxKind.VariableStatement: - return replaceInVariableStatement(parent as ts.VariableStatement, replacement, nodeFactory); - case SyntaxKind.VariableDeclaration: - return replaceInVariableDeclaration(parent as ts.VariableDeclaration, replacement, nodeFactory); - case SyntaxKind.VariableDeclarationList: - return replaceInVariableDeclarationList(parent as ts.VariableDeclarationList, replacement, nodeFactory); - case SyntaxKind.PropertyAssignment: - return replaceInPropertyAssignment(parent as ts.PropertyAssignment, replacement, nodeFactory); - case SyntaxKind.PropertyDeclaration: - return replaceInPropertyDeclaration(parent as ts.PropertyDeclaration, replacement, nodeFactory); - case SyntaxKind.IfStatement: - return replaceInIfStatement(parent as ts.IfStatement, replacement, nodeFactory); - case SyntaxKind.WhileStatement: - return replaceInWhileStatement(parent as ts.WhileStatement, replacement, nodeFactory); - case SyntaxKind.DoStatement: - return replaceInDoStatement(parent as ts.DoStatement, replacement, nodeFactory); - case SyntaxKind.ForStatement: - return replaceInForStatement(parent as ts.ForStatement, replacement, nodeFactory); - case SyntaxKind.ReturnStatement: - return replaceInReturnStatement(parent as ts.ReturnStatement, replacement, nodeFactory); - case SyntaxKind.ArrayLiteralExpression: - return replaceInArrayLiteralExpression(parent as ts.ArrayLiteralExpression, replacement, nodeFactory); - case SyntaxKind.ObjectLiteralExpression: - return replaceInObjectLiteralExpression(parent as ts.ObjectLiteralExpression, replacement, nodeFactory); - case SyntaxKind.PropertyAccessExpression: - return replaceInPropertyAccessExpression(parent as ts.PropertyAccessExpression, replacement, nodeFactory); - case SyntaxKind.ElementAccessExpression: - return replaceInElementAccessExpression(parent as ts.ElementAccessExpression, replacement, nodeFactory); - case SyntaxKind.Block: - return replaceInBlock(parent as ts.Block, replacement, nodeFactory); - case SyntaxKind.ArrowFunction: - return replaceInArrowFunction(parent as ts.ArrowFunction, replacement, nodeFactory); - case SyntaxKind.FunctionExpression: - return replaceInFunctionExpression(parent as ts.FunctionExpression, replacement, nodeFactory); - case SyntaxKind.FunctionDeclaration: - return replaceInFunctionDeclaration(parent as ts.FunctionDeclaration, replacement, nodeFactory); - case SyntaxKind.MethodDeclaration: - return replaceInMethodDeclaration(parent as ts.MethodDeclaration, replacement, nodeFactory); - case SyntaxKind.ClassDeclaration: - return replaceInClassDeclaration(parent as ts.ClassDeclaration, replacement, nodeFactory); - case SyntaxKind.ComputedPropertyName: - return replaceInComputedPropertyName(parent as ts.ComputedPropertyName, replacement, nodeFactory); - case SyntaxKind.Parameter: - return replaceInParameterDeclaration(parent as ts.ParameterDeclaration, replacement, nodeFactory); - case SyntaxKind.SourceFile: - return replaceInSourceFile(parent as ts.SourceFile, replacement, nodeFactory); - default: - throw new UnsupportedModuleError( + switch (parent.kind) { + case SyntaxKind.ExpressionStatement: + return replaceInExpressionStatement(parent as ts.ExpressionStatement, replacement, nodeFactory); + case SyntaxKind.ParenthesizedExpression: + return replaceInParenthesizedExpression(parent as ts.ParenthesizedExpression, replacement, nodeFactory); + case SyntaxKind.CallExpression: + return replaceInCallExpression(parent as ts.CallExpression, replacement, nodeFactory); + case SyntaxKind.NewExpression: + return replaceInNewExpression(parent as ts.NewExpression, replacement, nodeFactory); + case SyntaxKind.BinaryExpression: + return replaceInBinaryExpression(parent as ts.BinaryExpression, replacement, nodeFactory); + case SyntaxKind.ConditionalExpression: + return replaceInConditionalExpression(parent as ts.ConditionalExpression, replacement, nodeFactory); + case SyntaxKind.PrefixUnaryExpression: + return replaceInPrefixUnaryExpression(parent as ts.PrefixUnaryExpression, replacement, nodeFactory); + case SyntaxKind.PostfixUnaryExpression: + return replaceInPostfixUnaryExpression(parent as ts.PostfixUnaryExpression, replacement, nodeFactory); + case SyntaxKind.YieldExpression: + return replaceInYieldExpression(parent as ts.YieldExpression, replacement, nodeFactory); + case SyntaxKind.AwaitExpression: + return replaceInAwaitExpression(parent as ts.AwaitExpression, replacement, nodeFactory); + case SyntaxKind.VariableStatement: + return replaceInVariableStatement(parent as ts.VariableStatement, replacement, nodeFactory); + case SyntaxKind.VariableDeclaration: + return replaceInVariableDeclaration(parent as ts.VariableDeclaration, replacement, nodeFactory); + case SyntaxKind.VariableDeclarationList: + return replaceInVariableDeclarationList(parent as ts.VariableDeclarationList, replacement, nodeFactory); + case SyntaxKind.PropertyAssignment: + return replaceInPropertyAssignment(parent as ts.PropertyAssignment, replacement, nodeFactory); + case SyntaxKind.PropertyDeclaration: + return replaceInPropertyDeclaration(parent as ts.PropertyDeclaration, replacement, nodeFactory); + case SyntaxKind.IfStatement: + return replaceInIfStatement(parent as ts.IfStatement, replacement, nodeFactory); + case SyntaxKind.WhileStatement: + return replaceInWhileStatement(parent as ts.WhileStatement, replacement, nodeFactory); + case SyntaxKind.DoStatement: + return replaceInDoStatement(parent as ts.DoStatement, replacement, nodeFactory); + case SyntaxKind.ForStatement: + return replaceInForStatement(parent as ts.ForStatement, replacement, nodeFactory); + case SyntaxKind.ReturnStatement: + return replaceInReturnStatement(parent as ts.ReturnStatement, replacement, nodeFactory); + case SyntaxKind.ArrayLiteralExpression: + return replaceInArrayLiteralExpression(parent as ts.ArrayLiteralExpression, replacement, nodeFactory); + case SyntaxKind.ObjectLiteralExpression: + return replaceInObjectLiteralExpression(parent as ts.ObjectLiteralExpression, replacement, nodeFactory); + case SyntaxKind.PropertyAccessExpression: + return replaceInPropertyAccessExpression(parent as ts.PropertyAccessExpression, replacement, nodeFactory); + case SyntaxKind.ElementAccessExpression: + return replaceInElementAccessExpression(parent as ts.ElementAccessExpression, replacement, nodeFactory); + case SyntaxKind.Block: + return replaceInBlock(parent as ts.Block, replacement, nodeFactory); + case SyntaxKind.ArrowFunction: + return replaceInArrowFunction(parent as ts.ArrowFunction, replacement, nodeFactory); + case SyntaxKind.FunctionExpression: + return replaceInFunctionExpression(parent as ts.FunctionExpression, replacement, nodeFactory); + case SyntaxKind.FunctionDeclaration: + return replaceInFunctionDeclaration(parent as ts.FunctionDeclaration, replacement, nodeFactory); + case SyntaxKind.MethodDeclaration: + return replaceInMethodDeclaration(parent as ts.MethodDeclaration, replacement, nodeFactory); + case SyntaxKind.ClassDeclaration: + return replaceInClassDeclaration(parent as ts.ClassDeclaration, replacement, nodeFactory); + case SyntaxKind.ComputedPropertyName: + return replaceInComputedPropertyName(parent as ts.ComputedPropertyName, replacement, nodeFactory); + case SyntaxKind.Parameter: + return replaceInParameterDeclaration(parent as ts.ParameterDeclaration, replacement, nodeFactory); + case SyntaxKind.SourceFile: + return replaceInSourceFile(parent as ts.SourceFile, replacement, nodeFactory); + default: + throw new UnsupportedModuleError( `Unsupported parent node type for replacement operation: ${ts.SyntaxKind[parent.kind]} at ` + `${toPosStr(parent)}`); } diff --git a/src/detectors/transpilers/amd/requireExpressionToTransformation.ts b/src/detectors/transpilers/amd/requireExpressionToTransformation.ts index 9c30c3fc6..bd887aa50 100644 --- a/src/detectors/transpilers/amd/requireExpressionToTransformation.ts +++ b/src/detectors/transpilers/amd/requireExpressionToTransformation.ts @@ -5,14 +5,14 @@ import {ProbingRequireExpression, RequireExpression} from "./parseRequire.js"; const log = getLogger("transpilers:amd:transformRequireCall"); export interface RequireTransformationAsync { - imports: ts.ImportDeclaration[], - callback?: ts.CallExpression, - errback?: ts.FunctionDeclaration, + imports: ts.ImportDeclaration[]; + callback?: ts.CallExpression; + errback?: ts.FunctionDeclaration; } export interface RequireTransformationSync { - import: ts.ImportDeclaration, - requireStatement: ts.Identifier | ts.AsExpression // Identifier for JS transpilation, AsExpression for TS + import: ts.ImportDeclaration; + requireStatement: ts.Identifier | ts.AsExpression; // Identifier for JS transpilation, AsExpression for TS } export function transformAsyncRequireCall( @@ -49,14 +49,14 @@ export function transformAsyncRequireCall( let moduleSpecifier: ts.StringLiteral; if (!ts.isStringLiteralLike(dep)) { log.verbose(`Skipping non-string dependency entry of type ${ts.SyntaxKind[dep.kind]} at ` + - toPosStr(dep)); + toPosStr(dep)); return; } if (ts.isNoSubstitutionTemplateLiteral(dep)) { moduleSpecifier = nodeFactory.createStringLiteral(dep.text); // Set pos to the original position to preserve source mapping capability // (cast type to avoid TS error due to modifying a read only property) - (moduleSpecifier.pos as ts.Node["pos"]) = dep.pos; + (moduleSpecifier.pos) = dep.pos; } else { moduleSpecifier = dep; } @@ -65,7 +65,7 @@ export function transformAsyncRequireCall( // Generate variable name based on import module // Later this variable will be used to call the factory function identifier = nodeFactory.createUniqueName(dep.text.replace(/[^a-zA-Z0-9]/g, "_")); - } else if (callbackParams && callbackParams[i]) { + } else if (callbackParams?.[i]) { // Use factory parameter identifier as import identifier identifier = callbackParams[i]; } // else: Side effect imports. No identifier needed @@ -156,6 +156,6 @@ export function transformSyncRequireCall( const requireStatement = identifier; return { import: importDeclaration, - requireStatement + requireStatement, }; } diff --git a/src/detectors/transpilers/amd/rewriteExtendCall.ts b/src/detectors/transpilers/amd/rewriteExtendCall.ts index 3120ce9f3..f5c4b0d4e 100644 --- a/src/detectors/transpilers/amd/rewriteExtendCall.ts +++ b/src/detectors/transpilers/amd/rewriteExtendCall.ts @@ -75,7 +75,7 @@ function getClassBodyFromArguments( undefined, prop.initializer.body); } else if (ts.isObjectLiteralExpression(prop.initializer) && - ts.isIdentifier(prop.name) && prop.name.text === "metadata") { + ts.isIdentifier(prop.name) && prop.name.text === "metadata") { // Transform to *static* property declaration? // This would align it with how UI5 projects should declare metadata in TypeScript, // however it's unclear whether this helps our static analysis @@ -109,6 +109,5 @@ function getClassBodyFromArguments( `While generating class body: Unexpected property type ${ts.SyntaxKind[prop.kind]} at ` + toPosStr(prop)); } - - }).filter(_ => _) as ts.ClassElement[]; + }).filter((_) => _) as ts.ClassElement[]; } diff --git a/src/detectors/transpilers/amd/transpiler.ts b/src/detectors/transpilers/amd/transpiler.ts index 95fda556a..c2d56f9ac 100644 --- a/src/detectors/transpilers/amd/transpiler.ts +++ b/src/detectors/transpilers/amd/transpiler.ts @@ -21,7 +21,7 @@ export function amdToEsm(moduleId: string, content: string, strict?: boolean): T } catch (err) { if (err instanceof Error) { throw new Error(`Failed to transpile module ${moduleId}: ${err.message}`, { - cause: err + cause: err, }); } else { throw err; @@ -41,7 +41,7 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra { languageVersion: ts.ScriptTarget.ES2022, jsDocParsingMode: ts.JSDocParsingMode.ParseNone, - }, + } ); // Output @@ -62,13 +62,13 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra suppressOutputPathCheck: true, noLib: true, noResolve: true, - allowNonTsExtensions: true + allowNonTsExtensions: true, }; // TODO: Investigate whether it would be faster to create one host + program to transpile many files in // one batch const compilerHost: ts.CompilerHost = { - getSourceFile: fileName => fileName === inputFileName ? sourceFile : undefined, + getSourceFile: (fileName) => fileName === inputFileName ? sourceFile : undefined, writeFile: (name, text) => { if (name.endsWith(".map")) { if (sourceMapText) { @@ -85,7 +85,7 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra }, getDefaultLibFileName: () => "lib.d.ts", useCaseSensitiveFileNames: () => false, - getCanonicalFileName: fileName => fileName, + getCanonicalFileName: (fileName) => fileName, getCurrentDirectory: () => "", getNewLine: () => "\n", fileExists: (fileName): boolean => fileName === inputFileName, @@ -96,15 +96,15 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra const program = ts.createProgram([inputFileName], compilerOptions, compilerHost); const transformers: ts.CustomTransformers = { - before: [createTransformer(resourcePath, program)] + before: [createTransformer(resourcePath, program)], }; try { // ts.setEmitFlags(sourceFile, ts.EmitFlags.NoTrailingSourceMap); // TODO: Investigate whether we can retrieve a source file that can be fed directly into the typeChecker program.emit( - /*targetSourceFile*/ undefined, /*writeFile*/ undefined, - /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, + /* targetSourceFile */ undefined, /* writeFile */ undefined, + /* cancellationToken */ undefined, /* emitOnlyDtsFiles */ undefined, transformers); /* tsc currently does not provide an API to emit TypeScript *with* a source map @@ -121,7 +121,7 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra const printed = printer.printFile(result.transformed[0]); outputText = printed; */ - } catch(err) { + } catch (err) { if (strict) { throw err; } @@ -131,7 +131,7 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra log.verbose(`Stack trace:`); log.verbose(err.stack); } - return { source: content, map: "" }; + return {source: content, map: ""}; } else if (err instanceof Error && err.message.startsWith("Debug Failure")) { // We probably failed to create a valid AST log.verbose(`AST transformation failed for module ${resourcePath}: ${err.message}`); @@ -139,7 +139,7 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra log.verbose(`Stack trace:`); log.verbose(err.stack); } - return { source: content, map: "" }; + return {source: content, map: ""}; } throw err; } @@ -149,5 +149,5 @@ function transpile(resourcePath: string, content: string, strict?: boolean): Tra // Convert sourceMappingURL ending with ".js" to ".ts" outputText = outputText .replace(`//# sourceMappingURL=${sourceMapName}`, `//# sourceMappingURL=${outputFileName}.map`); - return { source: outputText, map: sourceMapText as string }; + return {source: outputText, map: sourceMapText!}; } diff --git a/src/detectors/transpilers/xml/Parser.ts b/src/detectors/transpilers/xml/Parser.ts index c57f43ffd..92fce349c 100644 --- a/src/detectors/transpilers/xml/Parser.ts +++ b/src/detectors/transpilers/xml/Parser.ts @@ -12,51 +12,51 @@ const log = getLogger("transpilers:xml:Parser"); export type Namespace = string; export interface NamespaceDeclaration { - localName: string | null, // null for default namespace - namespace: Namespace + localName: string | null; // null for default namespace + namespace: Namespace; } // Parse the XML node by node. We only expect four types of node // Once parsed, render the nodes as JavaScript code, starting with the leaves export const enum NodeKind { - Unknown = 0, - Control = 1 << 0, - Aggregation = 1 << 1, - FragmentDefinition = 1 << 2, - Template = 1 << 3, - Xhtml = 1 << 4, // Should generally be ignored - Svg = 1 << 5, // Should generally be ignored + Unknown = 0, + Control = 1 << 0, + Aggregation = 1 << 1, + FragmentDefinition = 1 << 2, + Template = 1 << 3, + Xhtml = 1 << 4, // Should generally be ignored + Svg = 1 << 5, // Should generally be ignored } export interface Position { - line: number, - column: number, + line: number; + column: number; } export interface NodeDeclaration { - kind: NodeKind, - name: string, - namespace: Namespace, - start: Position, - end: Position, + kind: NodeKind; + name: string; + namespace: Namespace; + start: Position; + end: Position; } export interface ControlDeclaration extends NodeDeclaration { - kind: NodeKind.Control, - properties: Set, - aggregations: Map, - variableName?: string, // Will be populated during generation phase + kind: NodeKind.Control; + properties: Set; + aggregations: Map; + variableName?: string; // Will be populated during generation phase } export interface AggregationDeclaration extends NodeDeclaration { - kind: NodeKind.Aggregation, - owner: ControlDeclaration, - controls: ControlDeclaration[], + kind: NodeKind.Aggregation; + owner: ControlDeclaration; + controls: ControlDeclaration[]; } export interface FragmentDefinitionDeclaration extends NodeDeclaration { - kind: NodeKind.FragmentDefinition, - controls: Set, + kind: NodeKind.FragmentDefinition; + controls: Set; } // interface TemplateDeclaration extends NodeDeclaration { @@ -64,50 +64,50 @@ export interface FragmentDefinitionDeclaration extends NodeDeclaration { // } interface AttributeDeclaration { - name: string, - value: string, - localNamespace?: string, - start: Position, - end: Position, + name: string; + value: string; + localNamespace?: string; + start: Position; + end: Position; } -interface PropertyDeclaration extends AttributeDeclaration {} +type PropertyDeclaration = AttributeDeclaration; export interface RequireExpression extends AttributeDeclaration { - declarations: RequireDeclaration[] + declarations: RequireDeclaration[]; } export interface RequireDeclaration { - moduleName: string, - variableName?: string, + moduleName: string; + variableName?: string; } interface NamespaceStackEntry { - namespace: NamespaceDeclaration, - level: number + namespace: NamespaceDeclaration; + level: number; } const XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"; const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; const TEMPLATING_NAMESPACE = "http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1"; -const FESR_NAMESPACE ="http://schemas.sap.com/sapui5/extension/sap.ui.core.FESR/1"; -const SAP_BUILD_NAMESPACE ="sap.build"; -const SAP_UI_DT_NAMESPACE ="sap.ui.dt"; -const CUSTOM_DATA_NAMESPACE ="http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"; +const FESR_NAMESPACE = "http://schemas.sap.com/sapui5/extension/sap.ui.core.FESR/1"; +const SAP_BUILD_NAMESPACE = "sap.build"; +const SAP_UI_DT_NAMESPACE = "sap.ui.dt"; +const CUSTOM_DATA_NAMESPACE = "http://schemas.sap.com/sapui5/extension/sap.ui.core.CustomData/1"; const CORE_NAMESPACE = "sap.ui.core"; const PATTERN_LIBRARY_NAMESPACES = /^([a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*)$/; const enum DocumentKind { View, - Fragment + Fragment, } function determineDocumentKind(resourceName: string): DocumentKind | null { - if ( /\.view.xml$/.test(resourceName) ) { + if (/\.view.xml$/.test(resourceName)) { return DocumentKind.View; - } else if ( /\.fragment.xml$/.test(resourceName) ) { + } else if (/\.fragment.xml$/.test(resourceName)) { return DocumentKind.Fragment; - } else if ( /\.control.xml$/.test(resourceName) ) { + } else if (/\.control.xml$/.test(resourceName)) { throw new Error(`Control XML analysis is currently not supported for resource ${resourceName}`); } else { return null; @@ -117,7 +117,7 @@ function determineDocumentKind(resourceName: string): DocumentKind | null { function toPosition(saxPos: SaxPosition): Position { return { line: saxPos.line, - column: saxPos.character + column: saxPos.character, }; } @@ -140,7 +140,8 @@ export default class Parser { this.#resourceName = resourceName; this.#xmlDocumentKind = xmlDocumentKind; this.#generator = xmlDocumentKind === DocumentKind.View ? - new ViewGenerator(resourceName) : new FragmentGenerator(resourceName); + new ViewGenerator(resourceName) : + new FragmentGenerator(resourceName); this.#apiExtract = apiExtract; } @@ -187,14 +188,14 @@ export default class Parser { return null; } - _addNamespace(namespace: NamespaceDeclaration, level: number,) { + _addNamespace(namespace: NamespaceDeclaration, level: number) { this.#namespaceStack.push({ namespace, - level + level, }); } - _resolveNamespace(localName: string | null,): Namespace | undefined { + _resolveNamespace(localName: string | null): Namespace | undefined { // Search this.#namespaceStack in reverse order for (let i = this.#namespaceStack.length - 1; i >= 0; i--) { const ns = this.#namespaceStack[i]; @@ -204,7 +205,7 @@ export default class Parser { } } - _removeNamespacesForLevel(level: number,) { + _removeNamespacesForLevel(level: number) { // Remove all namespaces for the given level let i = this.#namespaceStack.length - 1; while (i >= 0 && this.#namespaceStack[i].level >= level) { @@ -220,14 +221,14 @@ export default class Parser { if (!aggregationName) { log.verbose(`Failed to determine default aggregation for control ${owner.name} used in ` + - `resource ${this.#resourceName}. Falling back to 'dependents'`); + `resource ${this.#resourceName}. Falling back to 'dependents'`); // In case the default aggregation is unknown (e.g. in case of custom controls), // fallback to use the generic "dependents" aggregation // This is not correct at runtime, but it's the best we can do for linting purposes aggregationName = "dependents"; } if (!owner.aggregations.has(aggregationName)) { - const aggregation = { + const aggregation = { kind: NodeKind.Aggregation, name: aggregationName, owner, @@ -235,7 +236,7 @@ export default class Parser { namespace: owner.namespace, start: control.start, end: control.end, - }; + } as AggregationDeclaration; owner.aggregations.set(aggregationName, aggregation); } else { owner.aggregations.get(aggregationName)!.controls.push(control); @@ -249,7 +250,7 @@ export default class Parser { return Object.keys(requireMap).map((variableName) => { return { moduleName: requireMap[variableName], - variableName + variableName, }; }); } catch (err) { @@ -275,13 +276,13 @@ export default class Parser { // Declares the default namespace this._addNamespace({ localName: null, - namespace: attrValue + namespace: attrValue, }, this.#nodeStack.length); } else if (attrName.startsWith("xmlns:")) { // Named namespace this._addNamespace({ localName: attrName.slice(6), // Remove "xmlns:" - namespace: attrValue + namespace: attrValue, }, this.#nodeStack.length); } else if (attrName.includes(":")) { // Namespaced attribute @@ -293,8 +294,8 @@ export default class Parser { start: toPosition(attr.name.start), end: toPosition({ line: attr.value.end.line, - character: attr.value.end.character + 1 // Add 1 to include the closing quote - }) + character: attr.value.end.character + 1, // Add 1 to include the closing quote + }), }); } else { attributes.add({ @@ -303,8 +304,8 @@ export default class Parser { start: toPosition(attr.name.start), end: toPosition({ line: attr.value.end.line, - character: attr.value.end.character + 1 // Add 1 to include the closing quote - }) + character: attr.value.end.character + 1, // Add 1 to include the closing quote + }), }); } }); @@ -339,7 +340,7 @@ export default class Parser { column: tag.openStart.character, message: `Usage of native HTML in XML Views/Fragments is deprecated`, messageDetails: - `{@link topic:be54950cae1041f59d4aa97a6bade2d8 Using Native HTML in XML Views (deprecated)}` + `{@link topic:be54950cae1041f59d4aa97a6bade2d8 Using Native HTML in XML Views (deprecated)}`, }); return { kind: NodeKind.Xhtml, @@ -357,7 +358,6 @@ export default class Parser { end: toPosition(tag.openEnd), }; } else if (PATTERN_LIBRARY_NAMESPACES.test(namespace)) { - const lastIdx = tagName.lastIndexOf("."); if (lastIdx !== -1) { // Resolve namespace prefix, e.g. "sap:m.Button" @@ -411,7 +411,7 @@ export default class Parser { const variableName = requiredModuleName.replaceAll("/", "_"); requireDeclarations.push({ moduleName: requiredModuleName, - variableName + variableName, }); }); } else { @@ -423,32 +423,32 @@ export default class Parser { value: attr.value, declarations: requireDeclarations, start: attr.start, - end: attr.end + end: attr.end, } as RequireExpression; this.#generator.writeRequire(requireExpression); } else if (resolvedNamespace === FESR_NAMESPACE || - resolvedNamespace === SAP_BUILD_NAMESPACE || resolvedNamespace === SAP_UI_DT_NAMESPACE) { + resolvedNamespace === SAP_BUILD_NAMESPACE || resolvedNamespace === SAP_UI_DT_NAMESPACE) { // Silently ignore FESR, sap.build and sap.ui.dt attributes } else if (resolvedNamespace === CUSTOM_DATA_NAMESPACE) { // Add custom data element and add it as an aggregation - const customData: ControlDeclaration ={ + const customData: ControlDeclaration = { kind: NodeKind.Control, name: "CustomData", namespace: CORE_NAMESPACE, properties: new Set([ - { + { name: "key", value: attr.name, start: attr.start, end: attr.end, - }, - { + } as PropertyDeclaration, + { name: "value", value: attr.value, start: attr.start, end: attr.end, - } + } as PropertyDeclaration, ]), aggregations: new Map(), start: attr.start, @@ -460,10 +460,10 @@ export default class Parser { this.#generator.writeControl(customData); } else { log.warn(`Ignoring unknown namespaced attribute ${attr.localNamespace}:${attr.name} ` + - `for ${moduleName} in resource ${this.#resourceName}`); + `for ${moduleName} in resource ${this.#resourceName}`); } } else { - controlProperties.add(attr as PropertyDeclaration); + controlProperties.add(attr); } }); @@ -515,7 +515,7 @@ export default class Parser { } return ownerAggregation; } else if (this.#xmlDocumentKind === DocumentKind.Fragment && moduleName === "FragmentDefinition" && - namespace === CORE_NAMESPACE) { + namespace === CORE_NAMESPACE) { // This node declares a fragment definition const node: FragmentDefinitionDeclaration = { kind: NodeKind.FragmentDefinition, @@ -533,7 +533,7 @@ export default class Parser { } else { // This node declares a control // Or a fragment definition in case of a fragment - const node: ControlDeclaration ={ + const node: ControlDeclaration = { kind: NodeKind.Control, name: moduleName, namespace, @@ -557,13 +557,13 @@ export default class Parser { if (parentNode) { if (parentNode.kind === NodeKind.Control) { // Insert the current control in the default aggregation of the last control - this._addDefaultAggregation(parentNode as ControlDeclaration, node as ControlDeclaration); + this._addDefaultAggregation(parentNode as ControlDeclaration, node); } else if (parentNode.kind === NodeKind.Aggregation) { const aggregationNode = parentNode as AggregationDeclaration; aggregationNode.controls.push(node); } else if (parentNode.kind === NodeKind.FragmentDefinition) { // Add the control to the fragment definition - (parentNode as FragmentDefinitionDeclaration).controls.add(node as ControlDeclaration); + (parentNode as FragmentDefinitionDeclaration).controls.add(node); } else { throw new Error(`Unexpected node kind ${parentNode.kind} in resource ${this.#resourceName}`); } diff --git a/src/detectors/transpilers/xml/generator/AbstractGenerator.ts b/src/detectors/transpilers/xml/generator/AbstractGenerator.ts index 023f0f28e..3059ea273 100644 --- a/src/detectors/transpilers/xml/generator/AbstractGenerator.ts +++ b/src/detectors/transpilers/xml/generator/AbstractGenerator.ts @@ -1,13 +1,13 @@ import { - ControlDeclaration, RequireExpression, Position + ControlDeclaration, RequireExpression, Position, } from "../Parser.js"; import Writer from "./Writer.js"; interface ImportStatement { - moduleName: string - variableName: string, - start?: Position, - end?: Position, + moduleName: string; + variableName: string; + start?: Position; + end?: Position; } // TODO: Generate type information to make View#byId() access typed? @@ -80,7 +80,7 @@ export default abstract class AbstractGenerator { moduleName: declaration.moduleName, variableName: variableName, start: requireExpression.start, - end: requireExpression.end + end: requireExpression.end, }); }); } diff --git a/src/detectors/transpilers/xml/generator/Writer.ts b/src/detectors/transpilers/xml/generator/Writer.ts index 48ee0e3fc..440609de5 100644 --- a/src/detectors/transpilers/xml/generator/Writer.ts +++ b/src/detectors/transpilers/xml/generator/Writer.ts @@ -4,12 +4,12 @@ import {Position} from "../Parser.js"; const NL = "\n"; interface Mapping { - generated: Position - original: Position + generated: Position; + original: Position; } export default class Writer { - #buf: string = ""; + #buf = ""; // #map: GenMapping; #mappings = new Set(); lineOffset = 0; @@ -56,7 +56,7 @@ export default class Writer { start && this.#addMapping(start, { line: 0, - column: 0 + column: 0, }); this.lineOffset += lineOffset + 1; // Adding one for the additional new line @@ -64,7 +64,7 @@ export default class Writer { end && this.#addMapping(end, { line: lineOffset, - column: columnOffset + column: columnOffset, }); } @@ -92,7 +92,7 @@ export default class Writer { mapping.generated.column, 0, mapping.original.line, - mapping.original.column + mapping.original.column, ]; mappings[mapping.generated.line].push(segment); }); @@ -116,7 +116,7 @@ export default class Writer { line: this.lineOffset, column: this.columnOffset, }, - original: sourcePos + original: sourcePos, }); } diff --git a/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts b/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts index d6b20c3fb..b68e1e4c5 100644 --- a/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts +++ b/src/detectors/transpilers/xml/lib/JSTokenizer.d.ts @@ -1,7 +1,5 @@ -interface RequireMap { - [key: string]: string -} -export function parseJS(sSource: string): RequireMap +type RequireMap = Record; +export function parseJS(sSource: string): RequireMap; export default class JSTokenizer { - static parseJS(sSource: string): RequireMap + static parseJS(sSource: string): RequireMap; } diff --git a/src/detectors/transpilers/xml/transpiler.ts b/src/detectors/transpilers/xml/transpiler.ts index 37e698572..5207c8239 100644 --- a/src/detectors/transpilers/xml/transpiler.ts +++ b/src/detectors/transpilers/xml/transpiler.ts @@ -6,7 +6,7 @@ import {fileURLToPath} from "node:url"; import {taskStart} from "../../util/perf.js"; import {TranspileResult} from "../AbstractTranspiler.js"; import Parser from "./Parser.js"; -import { getLogger } from "@ui5/logger"; +import {getLogger} from "@ui5/logger"; const log = getLogger("transpilers:xml:transpiler"); @@ -35,7 +35,7 @@ export async function xmlToJs(resourceName: string, contentStream: ReadStream): } catch (err) { if (err instanceof Error) { throw new Error(`Failed to transpile resource ${resourceName}: ${err.message}`, { - cause: err + cause: err, }); } else { throw err; @@ -54,7 +54,7 @@ async function init() { return initializing = Promise.all([ fs.readFile(saxPath), - fs.readFile(new URL("../../../../resources/api-extract.json", import.meta.url), {encoding: "utf-8"}) + fs.readFile(new URL("../../../../resources/api-extract.json", import.meta.url), {encoding: "utf-8"}), ]).then(async (results) => { saxWasmBuffer = results[0]; apiExtract = JSON.parse(results[1]); @@ -90,7 +90,7 @@ async function transpileXmlToJs(resourceName: string, contentStream: ReadStream) contentStream.on("data", (chunk: Uint8Array) => { try { saxParser.write(chunk); - } catch(err) { + } catch (err) { if (err instanceof Error) { // In case of an error, destroy the content stream to make the // error bubble up to our callers diff --git a/src/detectors/typeChecker/FileLinter.ts b/src/detectors/typeChecker/FileLinter.ts index 38e7ed9c2..7e387a7ba 100644 --- a/src/detectors/typeChecker/FileLinter.ts +++ b/src/detectors/typeChecker/FileLinter.ts @@ -27,7 +27,7 @@ export default class FileLinter { } catch (err) { if (err instanceof Error) { throw new Error(`Failed to produce report for ${this.#filePath}: ${err.message}`, { - cause: err + cause: err, }); } throw err; @@ -45,7 +45,7 @@ export default class FileLinter { this.analyzePropertyAccessExpression(node as ts.CallExpression); // Check for global this.analyzeCallExpression(node as ts.CallExpression); // Check for deprecation } else if (node.kind === ts.SyntaxKind.PropertyAccessExpression || - node.kind === ts.SyntaxKind.ElementAccessExpression) { + node.kind === ts.SyntaxKind.ElementAccessExpression) { this.analyzePropertyAccessExpression( node as (ts.PropertyAccessExpression | ts.ElementAccessExpression)); // Check for global this.analyzePropertyAccessExpressionForDeprecation( @@ -58,7 +58,7 @@ export default class FileLinter { ts.forEachChild(node, this.#boundVisitNode); } - isDeprecated(symbol: ts.Symbol) : boolean { + isDeprecated(symbol: ts.Symbol): boolean { if (symbol && this.isSymbolOfUi5Type(symbol)) { const jsdocTags = symbol.getJsDocTags(this.#checker); for (const tag of jsdocTags) { @@ -83,7 +83,7 @@ export default class FileLinter { arg.properties.forEach((prop) => { if (ts.isPropertyAssignment(prop)) { // TODO: Necessary? const propNameIdentifier = prop.name as Identifier; - const propText = propNameIdentifier.escapedText! || propNameIdentifier.text; + const propText = propNameIdentifier.escapedText || propNameIdentifier.text; const propertySymbol = argumentType.getProperty(propText); // this.#checker.getContextualType(arg) // same as nodeType @@ -97,8 +97,8 @@ export default class FileLinter { severity: LintMessageSeverity.Error, ruleId: "ui5-linter-no-deprecated-api", message: `Use of deprecated property '${propertySymbol.escapedName}' ` + - `of class '${this.#checker.typeToString(nodeType)}'`, - messageDetails: this.extractDeprecatedMessage(propertySymbol) + `of class '${this.#checker.typeToString(nodeType)}'`, + messageDetails: this.extractDeprecatedMessage(propertySymbol), }); } } @@ -108,7 +108,7 @@ export default class FileLinter { }); } - extractNamespace(node: ts.PropertyAccessExpression) : string { + extractNamespace(node: ts.PropertyAccessExpression): string { const propAccessChain: string[] = []; propAccessChain.push(node.expression.getText()); @@ -125,12 +125,12 @@ export default class FileLinter { return propAccessChain.join("."); } - extractDeprecatedMessage(symbol: ts.Symbol) : string { + extractDeprecatedMessage(symbol: ts.Symbol): string { if (symbol && this.isSymbolOfUi5Type(symbol)) { const jsdocTags = symbol.getJsDocTags(this.#checker); const deprecatedTag = jsdocTags.find((tag) => tag.name === "deprecated"); - if (deprecatedTag && deprecatedTag.text) { + if (deprecatedTag?.text) { // (Workaround) There's an issue in some UI5 TS definition versions and where the // deprecation text gets merged with the description. Splitting on double // new line could be considered as a clear separation between them. @@ -160,7 +160,7 @@ export default class FileLinter { if (!ts.isPropertyAccessExpression(exprNode) && !ts.isElementAccessExpression(exprNode) && - !ts.isIdentifier(exprNode)) { + !ts.isIdentifier(exprNode)) { // TODO: Transform into coverage message if it's really ok not to handle this throw new Error(`Unhandled CallExpression expression syntax: ${ts.SyntaxKind[exprNode.kind]}`); } @@ -197,11 +197,11 @@ export default class FileLinter { message: `Call to deprecated function ` + `'${symbol.escapedName}'${additionalMessage}`, - messageDetails: this.extractDeprecatedMessage(symbol) + messageDetails: this.extractDeprecatedMessage(symbol), }); } - isDeprecatedAccess(node: ts.AccessExpression) : ts.Symbol | undefined{ + isDeprecatedAccess(node: ts.AccessExpression): ts.Symbol | undefined { let symbol; if (ts.isPropertyAccessExpression(node)) { symbol = this.#checker.getSymbolAtLocation(node.name); @@ -213,7 +213,7 @@ export default class FileLinter { } } - isDeprecatedType(nodeType: ts.Type) : boolean { + isDeprecatedType(nodeType: ts.Type): boolean { if (nodeType.symbol && this.isDeprecated(nodeType.symbol)) { return true; } @@ -235,7 +235,7 @@ export default class FileLinter { message: `Access of deprecated property ` + `'${symbol.escapedName}'`, - messageDetails: this.extractDeprecatedMessage(symbol) + messageDetails: this.extractDeprecatedMessage(symbol), }); } } @@ -253,7 +253,7 @@ export default class FileLinter { message: `Unable to analyze this method call because the type of identifier` + `${identifier ? " \"" + identifier.getText() + "\"" : ""} in "${node.getText()}"" ` + - `could not be determined` + `could not be determined`, }); } } @@ -293,14 +293,13 @@ export default class FileLinter { severity: LintMessageSeverity.Error, ruleId: "ui5-linter-no-globals-js", message: - `Access of global variable '${symbol.getName()}' `+ - `(${this.extractNamespace(node)})` + `Access of global variable '${symbol.getName()}' ` + + `(${this.extractNamespace((node as ts.PropertyAccessExpression))})`, }); } } } - isAllowedPropertyAccess(node: ts.PropertyAccessExpression): boolean { if (!ts.isIdentifier(node.expression)) { // TODO: Fixme if this happens @@ -316,7 +315,7 @@ export default class FileLinter { "sap.ui.define", "sap.ui.require", "sap.ui.require.toUrl", - "sap.ui.loader.config" + "sap.ui.loader.config", ].some((allowedAccessString) => { return propAccess == allowedAccessString || propAccess.startsWith(allowedAccessString + "."); }); @@ -372,7 +371,7 @@ export default class FileLinter { return false; } - findClassOrInterface(node: ts.Node) : ts.Type | undefined { + findClassOrInterface(node: ts.Node): ts.Type | undefined { let nodeType: ts.Type | undefined = this.#checker.getTypeAtLocation(node); if (nodeType.isClassOrInterface()) { return nodeType; diff --git a/src/detectors/typeChecker/host.ts b/src/detectors/typeChecker/host.ts index 91678db74..c208c811d 100644 --- a/src/detectors/typeChecker/host.ts +++ b/src/detectors/typeChecker/host.ts @@ -37,7 +37,7 @@ export async function createVirtualCompilerHost( typePackages.forEach((pkgName) => { addPathMappingForPackage(pkgName, typePathMappings); }); - const typePackageDirs = Array.from(typePackages.keys()).map(pkgName => `/types/${pkgName}/`); + const typePackageDirs = Array.from(typePackages.keys()).map((pkgName) => `/types/${pkgName}/`); typePackageDirs.push("/types/@ui5/linter/overrides"); typePathMappings.set("@ui5/linter/overrides", path.dirname( @@ -66,7 +66,7 @@ export async function createVirtualCompilerHost( } } - function getFile(fileName: string) : string | undefined { + function getFile(fileName: string): string | undefined { // NOTE: This function should be kept in sync with "fileExists" if (files.has(fileName)) { @@ -184,7 +184,7 @@ export async function createVirtualCompilerHost( notImplemented("write"); // files.set(fileName, contents); }, - getCanonicalFileName: fileName => fileName, + getCanonicalFileName: (fileName) => fileName, getDefaultLibFileName: (defaultLibOptions: ts.CompilerOptions) => { return ts.getDefaultLibFileName(defaultLibOptions); }, diff --git a/src/detectors/typeChecker/index.ts b/src/detectors/typeChecker/index.ts index cc1af5ccc..030f1994c 100644 --- a/src/detectors/typeChecker/index.ts +++ b/src/detectors/typeChecker/index.ts @@ -10,7 +10,7 @@ import {amdToEsm} from "../transpilers/amd/transpiler.js"; import {xmlToJs} from "../transpilers/xml/transpiler.js"; import {lintManifest} from "../../linter/json/linter.js"; import { - FileBasedDetector, LintMessage, LintMessageSeverity, LintResult, ProjectBasedDetector + FileBasedDetector, LintMessage, LintMessageSeverity, LintResult, ProjectBasedDetector, } from "../AbstractDetector.js"; import {Project} from "@ui5/project"; import {Resource} from "@ui5/fs"; @@ -44,7 +44,7 @@ const DEFAULT_OPTIONS: ts.CompilerOptions = { // During transpilation, for every library module (where no default export exists), // an "import * as ABC" instead of a default import is created. // This logic needs to be in sync with the generator for UI5 TypeScript definitions. - allowSyntheticDefaultImports: true + allowSyntheticDefaultImports: true, }; export class TsProjectDetector extends ProjectBasedDetector { @@ -53,12 +53,12 @@ export class TsProjectDetector extends ProjectBasedDetector { constructor(project: Project) { super(project); - this.compilerOptions = { ...DEFAULT_OPTIONS }; + this.compilerOptions = {...DEFAULT_OPTIONS}; const namespace = project.getNamespace(); this.#projectBasePath = `/resources/${namespace}/`; this.compilerOptions.paths = { - [`${namespace}/*`]: [`${this.#projectBasePath}*`] + [`${namespace}/*`]: [`${this.#projectBasePath}*`], }; } @@ -66,13 +66,13 @@ export class TsProjectDetector extends ProjectBasedDetector { source: string, map: string | undefined) { const transformedWriter = createAdapter({ fsBasePath, - virBasePath: "/" + virBasePath: "/", }); await transformedWriter.write( createResource({ path: originalResourcePath + ".ui5lint.transformed.js", - string: source + string: source, }) ); @@ -80,7 +80,7 @@ export class TsProjectDetector extends ProjectBasedDetector { await transformedWriter.write( createResource({ path: originalResourcePath + ".ui5lint.transformed.js.map", - string: JSON.stringify(JSON.parse(map), null, "\t") + string: JSON.stringify(JSON.parse(map), null, "\t"), }) ); } @@ -106,16 +106,16 @@ export class TsProjectDetector extends ProjectBasedDetector { if (resourcePath.endsWith(".xml")) { resourcePath = resourcePath.replace(/\.xml$/, ".js"); const resourceContent = await resource.getStream(); - ({ source, map, messages } = + ({source, map, messages} = await xmlToJs(path.basename(originalResourcePath), resourceContent)); } else if (resourcePath.endsWith(".js")) { const resourceContent = await resource.getString(); const id = this.getModuleId(resourcePath); - ({ source, map } = amdToEsm(id, resourceContent)); + ({source, map} = amdToEsm(id, resourceContent)); } else if (resourcePath.endsWith(".json")) { resourcePath = resourcePath.replace(/\.json$/, ".js"); const resourceContent = await resource.getString(); - ({ source, messages } = await lintManifest(resourcePath, resourceContent)); + ({source, messages} = await lintManifest(resourcePath, resourceContent)); } else { throw new Error(`Unsupported file type for ${resourcePath}`); } @@ -126,7 +126,7 @@ export class TsProjectDetector extends ProjectBasedDetector { severity: LintMessageSeverity.Error, message, ruleId: "ui5-linter-parsing-error", - fatal: true + fatal: true, }); result.push(errorLinterReporter.getReport()); return; @@ -134,7 +134,7 @@ export class TsProjectDetector extends ProjectBasedDetector { vfsToFsPaths.set(resourcePath, fsPath); resources.set(resourcePath, source); - if (messages && messages.length) { + if (messages?.length) { resourceMessages.set(resourcePath, messages); } if (map) { @@ -150,7 +150,7 @@ export class TsProjectDetector extends ProjectBasedDetector { async createReports(filePaths: string[]) { const result: LintResult[] = []; const reader = this.project.getReader({ - style: "buildtime" + style: "buildtime", }); // Read all resources and test-resources and their content since tsc works completely synchronous @@ -254,7 +254,7 @@ export class TsFileDetector extends FileBasedDetector { async createReports(filePaths: string[]) { const options: ts.CompilerOptions = { ...DEFAULT_OPTIONS, - rootDir: this.rootDir + rootDir: this.rootDir, }; const resources = new Map(); @@ -285,12 +285,12 @@ export class TsFileDetector extends FileBasedDetector { } else { throw new Error(`Unsupported file type for ${filePath}`); } - const { source, map } = transformationResult; + const {source, map} = transformationResult; resources.set(internalfilePath, source); if (map) { sourceMaps.set(internalfilePath, map); } - if (transformationResult.messages && transformationResult.messages.length) { + if (transformationResult.messages?.length) { resourceMessages.set(internalfilePath, transformationResult.messages); } diff --git a/src/formatter/coverage.ts b/src/formatter/coverage.ts index a798e6ac6..df67899c3 100644 --- a/src/formatter/coverage.ts +++ b/src/formatter/coverage.ts @@ -3,13 +3,13 @@ import { LintResult, LintMessageSeverity, CoverageInfo, - CoverageCategory + CoverageCategory, } from "../detectors/AbstractDetector.js"; import {readFile} from "fs/promises"; const visualizedSpace = "\u00b7"; const visualizedTab = "\u00bb"; -const visualizedTabs : string[] = []; +const visualizedTabs: string[] = []; function formatSeverity(severity: LintMessageSeverity) { if (severity === LintMessageSeverity.Error) { @@ -24,9 +24,9 @@ function formatSeverity(severity: LintMessageSeverity) { function expandTabs(line: string, tabsize = 4) { let last = 0; let length = 0; - return line.replace(/[ \t]/g, function(tab, offset) { + return line.replace(/[ \t]/g, function (tab, offset) { length += offset - last; - if ( tab === "\t" ) { + if (tab === "\t") { const n = tabsize - length % tabsize; length += n; last++; @@ -43,11 +43,9 @@ function escape(str: string) { } export class Coverage { - #buffer: string = ""; + #buffer = ""; async format(lintResults: LintResult[]) { - - this.#writeln(` @@ -151,8 +149,8 @@ export class Coverage { #write(str: string) { this.#buffer += str; } + #writeln(str: string) { this.#buffer += str + "\n"; } - } diff --git a/src/formatter/json.ts b/src/formatter/json.ts index 9c694eb72..6dc5e7550 100644 --- a/src/formatter/json.ts +++ b/src/formatter/json.ts @@ -1,4 +1,4 @@ -import { LintMessage, LintResult } from "../detectors/AbstractDetector.js"; +import {LintMessage, LintResult} from "../detectors/AbstractDetector.js"; export class Json { format(lintResults: LintResult[], showDetails: boolean) { @@ -9,11 +9,11 @@ export class Json { | "errorCount" | "warningCount" | "fatalErrorCount" - //excluded by default: "coverageInfo" + // excluded by default: "coverageInfo" >[] = []; lintResults.forEach((oLintedFile) => { let aFileMessages: LintMessage[] = oLintedFile.messages; - + // Ignore files without findings (empty messages) if (aFileMessages && aFileMessages.length > 0) { // Exclude messageDetails property if CLI option "details" was not provided diff --git a/src/formatter/lib/resolveLinks.ts b/src/formatter/lib/resolveLinks.ts index 233344ede..cce436d05 100644 --- a/src/formatter/lib/resolveLinks.ts +++ b/src/formatter/lib/resolveLinks.ts @@ -1,9 +1,8 @@ // This file is a modified copy of ui5-builder/lib/processors/jsdoc/lib/transformApiJson.cjs // Its purpose is to try to resolve links in lint messages, derived from JSDoc annotations. -function JSDocUtil(): - {formatTextBlock: (src: string, linkFormatter: (target: string, text: string) => string) => string} { - +function JSDocUtil(): +{formatTextBlock: (src: string, linkFormatter: (target: string, text: string) => string) => string} { function format(src: string, linkFormatter: (target: string, text: string) => string): string { /* * regexp to recognize important places in the text @@ -16,8 +15,8 @@ function JSDocUtil(): * group 5: target portion of an inline @link tag * group 6: (optional) text portion of an inline link tag * group 7: an empty line which implicitly starts a new paragraph - * - * [--
 block -] [---- some header ----] [---- an inline [@link ...} tag ----] 
+		 *
+		 *      [-- 
 block -] [---- some header ----] [---- an inline [@link ...} tag ----]
 		 *      [---------- an empty line ---------]
 		 */
 		const r =
@@ -45,17 +44,17 @@ function JSDocUtil():
 	};
 }
 
-function formatUrlToLink (sTarget: string, sText: string): string {
+function formatUrlToLink(sTarget: string, sText: string): string {
 	return `${sText} (${sTarget})`;
 }
 
 function createLink({name, type, className, text = name, hrefAppend = "", ui5Url}:
-	Record): string {
+Record): string {
 	let sLink;
 	// handling module's
 	if (
 		className !== undefined &&
-		(/^module:/.test(name) || /^module:/.test(className))
+		(name.startsWith("module:") || className.startsWith("module:"))
 	) {
 		name = name.replace(/^module:/, "");
 	}
@@ -68,21 +67,21 @@ function createLink({name, type, className, text = name, hrefAppend = "", ui5Url
 	return `${text} (${ui5Url}/api/${sLink})`;
 }
 
-function _preProcessLinksInTextBlock (sText: string, ui5Url: string): string {
+function _preProcessLinksInTextBlock(sText: string, ui5Url: string): string {
 	const linkFormatter = function (sTarget: string, sText: string): string {
 		let aMatch;
 		// keep the full target in the fallback text
 		sText = sText || sTarget;
-		
+
 		if (sTarget === "module" && sText.startsWith(":")) {
 			const textChunks = sText.split(" ");
-			sTarget += textChunks[0]; 
+			sTarget += textChunks[0];
 			sText = textChunks[1] || textChunks[0].substring(1);
 		} else if (sTarget === "topic" && sText.startsWith(":")) {
 			sTarget += sText.split(" ")[0];
 			sText = sText.split(" ").slice(1).join(" ");
 		}
-		
+
 		// If the link has a protocol, do not modify, but open in a new window
 		if (/:\/\//.test(sTarget)) {
 			return formatUrlToLink(sTarget, sText);
@@ -271,7 +270,7 @@ function _preProcessLinksInTextBlock (sText: string, ui5Url: string): string {
 	return JSDocUtil().formatTextBlock(sText, linkFormatter);
 }
 
-export function resolveLinks (description?: string, ui5Url: string = "https://ui5.sap.com/1.120/#"): string {
+export function resolveLinks(description?: string, ui5Url = "https://ui5.sap.com/1.120/#"): string {
 	if (!description) {
 		return "";
 	}
diff --git a/src/formatter/text.ts b/src/formatter/text.ts
index 17960a297..395b62467 100644
--- a/src/formatter/text.ts
+++ b/src/formatter/text.ts
@@ -13,7 +13,6 @@ function formatSeverity(severity: LintMessageSeverity) {
 
 function formatLocation(line: LintMessage["line"], column: LintMessage["column"],
 	lineInfoLength: number, columnInfoLength: number) {
-
 	const lineStr = (line === undefined ? "?" : line.toString()).padStart(lineInfoLength, " ");
 	const columnStr = (column === undefined ? "?" : column.toString()).padEnd(columnInfoLength, " ");
 
@@ -21,7 +20,7 @@ function formatLocation(line: LintMessage["line"], column: LintMessage["column"]
 }
 
 export class Text {
-	#buffer: string = "";
+	#buffer = "";
 
 	format(lintResults: LintResult[], showDetails: boolean) {
 		this.#writeln("");
@@ -75,15 +74,15 @@ export class Text {
 				if (messages) {
 					this.#writeln(chalk.bold(`  ${ruleId} (${messages.length})`));
 					messages.forEach((msg) => {
-						const messageDetails = (showDetails && msg.messageDetails) ? 
-							(`\n      ${chalk.white.bold("Details:")}\n      ` +
-							`${chalk.italic(msg.messageDetails.replaceAll("\n", "\n      "))}`) : 
+						const messageDetails = (showDetails && msg.messageDetails) ?
+								(`\n      ${chalk.white.bold("Details:")}\n      ` +
+								`${chalk.italic(msg.messageDetails.replaceAll("\n", "\n      "))}`) :
 							"";
 
 						this.#writeln(
 							`    ${formatLocation(msg.line, msg.column, lineInfoLength, columnInfoLength)} ` +
 							`${formatSeverity(msg.severity)} ` +
-							`${msg.message}` + 
+							`${msg.message}` +
 							`${messageDetails}`);
 
 						addNewLineAfterModule = true;
@@ -110,15 +109,16 @@ export class Text {
 		if (!showDetails && (totalErrorCount + totalWarningCount + totalFatalErrorCount) > 0) {
 			this.#writeln("");
 			this.#writeln(chalk.dim.bold("Note: ") +
-				chalk.dim(`Use "ui5lint --details" to show more information about the findings`));
+			chalk.dim(`Use "ui5lint --details" to show more information about the findings`));
 		}
-		
+
 		return this.#buffer;
 	}
 
 	#write(str: string) {
 		this.#buffer += str;
 	}
+
 	#writeln(str: string) {
 		this.#buffer += str + "\n";
 	}
diff --git a/src/linter/json/ManifestLinter.ts b/src/linter/json/ManifestLinter.ts
index c8e936ca6..08783ec7e 100644
--- a/src/linter/json/ManifestLinter.ts
+++ b/src/linter/json/ManifestLinter.ts
@@ -3,7 +3,7 @@ import type {
 	JSONSchemaForSAPUI5Namespace,
 	JSONSchemaForSAPAPPNamespace,
 	Model as ManifestModel,
-	DataSource as ManifestDataSource
+	DataSource as ManifestDataSource,
 } from "../../manifest.d.ts";
 import type {LintResult} from "../../detectors/AbstractDetector.js";
 
@@ -11,23 +11,23 @@ import ManifestReporter from "./ManifestReporter.js";
 import {LintMessageSeverity} from "../../detectors/AbstractDetector.js";
 import jsonMap from "json-source-map";
 
-type locType = {
-	line: number,
-	column: number,
-	pos: number,
+interface locType {
+	line: number;
+	column: number;
+	pos: number;
 }
 
-export type jsonMapPointers = Record;
+export type jsonMapPointers = Record;
 
-export type jsonSourceMapType = {
-	data: SAPJSONSchemaForWebApplicationManifestFile,
-	pointers: jsonMapPointers
+export interface jsonSourceMapType {
+	data: SAPJSONSchemaForWebApplicationManifestFile;
+	pointers: jsonMapPointers;
 }
 
 export default class ManifestLinter {
 	#reporter: ManifestReporter | null;
-	#content: string = "";
-	#path: string = "";
+	#content = "";
+	#path = "";
 
 	constructor(content: string, path: string) {
 		this.#reporter = null;
@@ -49,10 +49,10 @@ export default class ManifestLinter {
 	}
 
 	#analyzeManifest(manifest: SAPJSONSchemaForWebApplicationManifestFile) {
-		const {resources, models} = manifest["sap.ui5"] ?? {};
-		const {dataSources} = manifest["sap.app"] ?? {};
+		const {resources, models} = manifest["sap.ui5"]! ?? {};
+		const {dataSources} = manifest["sap.app"] ?? {};
 
-		if (resources && resources.js) {
+		if (resources?.js) {
 			this.#reporter?.addMessage({
 				node: "/sap.ui5/resources/js",
 				severity: LintMessageSeverity.Error,
@@ -63,11 +63,11 @@ export default class ManifestLinter {
 
 		const modelKeys: string[] = (models && Object.keys(models)) || [];
 		modelKeys.forEach((modelKey: string) => {
-			const curModel: ManifestModel = (models && (models[modelKey])) || {};
+			const curModel: ManifestModel = (models?.[modelKey])) || {};
 
 			if (!curModel.type) {
 				const curDataSource = dataSources && curModel.dataSource &&
-					dataSources[curModel.dataSource];
+					dataSources[curModel.dataSource];
 
 				if (curDataSource &&
 					/* if not provided dataSource.type="OData" */
@@ -82,26 +82,25 @@ export default class ManifestLinter {
 
 			if (curModel.type && [
 				"sap.ui.model.odata.ODataModel",
-				"sap.zen.dsh.widgets.SDKModel"
+				"sap.zen.dsh.widgets.SDKModel",
 			].includes(curModel.type)) {
 				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}"'`
+					`'sap.ui5/models/${modelKey}/type="${curModel.type}"'`,
 				});
 			}
 
 			if (curModel.type === "sap.ui.model.odata.v4.ODataModel" &&
 				curModel.settings && "synchronizationMode" in curModel.settings) {
-
 				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`
+					`'sap.ui5/models/${modelKey}/settings/synchronizationMode' of sap.ui.model.odata.v4.ODataModel`,
 				});
 			}
 		});
diff --git a/src/linter/json/ManifestReporter.ts b/src/linter/json/ManifestReporter.ts
index fb71d1ef5..0ffec046b 100644
--- a/src/linter/json/ManifestReporter.ts
+++ b/src/linter/json/ManifestReporter.ts
@@ -1,9 +1,8 @@
-import type {BaseReporter, ReporterMessage, ReporterCoverageInfo, PositionInfo,} from "../../detectors/BaseReporter.js";
+import type {BaseReporter, ReporterMessage, ReporterCoverageInfo, PositionInfo} from "../../detectors/BaseReporter.js";
 import type {LintMessage} from "../../detectors/AbstractDetector.js";
 import type {jsonSourceMapType, jsonMapPointers} from "./ManifestLinter.js";
 import {LintMessageSeverity, CoverageInfo} from "../../detectors/AbstractDetector.js";
 
-
 export default class ManifestReporter implements BaseReporter {
 	#filePath: string;
 	#pointers: jsonMapPointers;
@@ -20,7 +19,7 @@ export default class ManifestReporter implements BaseReporter {
 			throw new Error(`Reports flagged as "fatal" must be of severity "Error"`);
 		}
 
-		const {line, column} = this.#getPosition(node);
+		const {line, column} = this.#getPosition((node as string));
 
 		this.#messages.push({
 			ruleId,
@@ -33,7 +32,7 @@ export default class ManifestReporter implements BaseReporter {
 	}
 
 	addCoverageInfo({node, message, category}: ReporterCoverageInfo) {
-		const location = this.#getPositionsForNode(node);
+		const location = this.#getPositionsForNode((node as string));
 		this.#coverageInfo.push({
 			category,
 			// One-based to be aligned with most IDEs
@@ -64,7 +63,7 @@ export default class ManifestReporter implements BaseReporter {
 
 		return {
 			line,
-			column
+			column,
 		};
 	}
 
diff --git a/src/linter/json/linter.ts b/src/linter/json/linter.ts
index 942072c11..399cc3926 100644
--- a/src/linter/json/linter.ts
+++ b/src/linter/json/linter.ts
@@ -1,4 +1,3 @@
-
 import ManifestLinter from "./ManifestLinter.js";
 import {taskStart} from "../../detectors/util/perf.js";
 
@@ -11,4 +10,4 @@ export async function lintManifest(resourceName: string, content: string): Promi
 	taskLintEnd();
 
 	return {messages, source: content, map: ""};
-}
\ No newline at end of file
+}
diff --git a/src/linter/linter.ts b/src/linter/linter.ts
index 4c97829b2..5828d95ca 100644
--- a/src/linter/linter.ts
+++ b/src/linter/linter.ts
@@ -6,8 +6,8 @@ import path from "node:path";
 import {stat} from "node:fs/promises";
 
 interface LinterOptions {
-	rootDir: string,
-	filePaths: string[]
+	rootDir: string;
+	filePaths: string[];
 }
 
 async function fsStat(fsPath: string) {
@@ -46,8 +46,8 @@ async function getProjectGraph(rootDir: string) {
 				specVersion: "3.0",
 				type: "application",
 				metadata: {
-					name: "ui5-linter-target"
-				}
+					name: "ui5-linter-target",
+				},
 			};
 		} else {
 			const isLibrary = await dirExists(path.join(rootDir, "src"));
@@ -56,8 +56,8 @@ async function getProjectGraph(rootDir: string) {
 					specVersion: "3.0",
 					type: "library",
 					metadata: {
-						name: "ui5-linter-target"
-					}
+						name: "ui5-linter-target",
+					},
 				};
 			}
 		}
@@ -75,15 +75,15 @@ async function getProjectGraph(rootDir: string) {
 			id: "ui5-linter-target",
 			version: "1.0.0",
 			path: rootDir,
-			dependencies: []
+			dependencies: [],
 		},
 		rootConfigPath,
 		rootConfiguration,
-		resolveFrameworkDependencies: false
+		resolveFrameworkDependencies: false,
 	});
 }
 
-export async function lintProject({rootDir, filePaths}: LinterOptions) : Promise {
+export async function lintProject({rootDir, filePaths}: LinterOptions): Promise {
 	const lintEnd = taskStart("Linting Project");
 	const projectGraphDone = taskStart("Project Graph creation");
 	const graph = await getProjectGraph(rootDir);
@@ -95,7 +95,7 @@ export async function lintProject({rootDir, filePaths}: LinterOptions) : Promise
 	return res;
 }
 
-export async function lintFile({rootDir, filePaths}: LinterOptions) : Promise {
+export async function lintFile({rootDir, filePaths}: LinterOptions): Promise {
 	const tsDetector = new TsFileDetector(rootDir);
 	return await tsDetector.createReports(filePaths);
 }
diff --git a/src/untyped.d.ts b/src/untyped.d.ts
index 28f7ca57c..218ed982a 100644
--- a/src/untyped.d.ts
+++ b/src/untyped.d.ts
@@ -1,7 +1,7 @@
 declare module "@ui5/to-esm" {
 	interface Result {
-		source: string,
-		map: string
+		source: string;
+		map: string;
 	}
 	export default function ui5ToESM(content: string, options: object): Result;
 }
@@ -11,20 +11,20 @@ declare module "@ui5/project" {
 
 	type ProjectNamespace = string;
 	interface Project {
-		getNamespace: () => ProjectNamespace,
-		getReader: (options: ReaderOptions) => AbstractReader,
-		getRootPath: () => string,
+		getNamespace: () => ProjectNamespace;
+		getReader: (options: ReaderOptions) => AbstractReader;
+		getRootPath: () => string;
 	}
 	interface ProjectGraph {
-		getRoot: () => Project
+		getRoot: () => Project;
 	}
 	interface DependencyTreeNode {
-		id: string,
-		version: string,
-		path: string,
-		configuration?: object | object[],
-		configPath?: string,
-		dependencies: DependencyTreeNode[]
+		id: string;
+		version: string;
+		path: string;
+		configuration?: object | object[];
+		configPath?: string;
+		dependencies: DependencyTreeNode[];
 	}
 }
 
@@ -32,7 +32,7 @@ declare module "@ui5/project/ui5Framework/maven/CacheMode" {
 	enum CacheMode {
 		Default = "Default",
 		Force = "Force",
-		Off = "Off"
+		Off = "Off",
 	}
 	export default CacheMode;
 }
@@ -41,88 +41,88 @@ declare module "@ui5/project/graph" {
 	import type CacheMode from "@ui5/project/ui5Framework/maven/CacheMode";
 
 	interface GraphFromObjectOptions {
-		dependencyTree: DependencyTreeNode,
-		cwd?: string,
-		rootConfiguration?: object,
-		rootConfigPath?: string,
-		versionOverride?: string,
-		cacheMode?: CacheMode,
-		resolveFrameworkDependencies?: boolean,
+		dependencyTree: DependencyTreeNode;
+		cwd?: string;
+		rootConfiguration?: object;
+		rootConfigPath?: string;
+		versionOverride?: string;
+		cacheMode?: CacheMode;
+		resolveFrameworkDependencies?: boolean;
 	}
-	export function graphFromObject(options: GraphFromObjectOptions): Promise
+	export function graphFromObject(options: GraphFromObjectOptions): Promise;
 
 	interface GraphFromPackageDependenciesOptions {
-		cwd?: string,
-		rootConfiguration?: object,
-		rootConfigPath?: string,
-		versionOverride?: string,
-		cacheMode?: CacheMode,
-		resolveFrameworkDependencies?: boolean,
-		workspaceName?: string,
-		workspaceConfiguration?: object,
-		workspaceConfigPath?: string
+		cwd?: string;
+		rootConfiguration?: object;
+		rootConfigPath?: string;
+		versionOverride?: string;
+		cacheMode?: CacheMode;
+		resolveFrameworkDependencies?: boolean;
+		workspaceName?: string;
+		workspaceConfiguration?: object;
+		workspaceConfigPath?: string;
 	}
-	export function graphFromPackageDependencies(options?: GraphFromPackageDependenciesOptions): Promise
+	export function graphFromPackageDependencies(options?: GraphFromPackageDependenciesOptions): Promise;
 }
 
 declare module "@ui5/fs" {
 	type ResourcePath = string;
 	interface ResourceSourceMetadata {
-		fsPath: string
+		fsPath: string;
 	}
 	interface Resource {
-		getBuffer: () => Promise,
-		getString: () => Promise,
-		getStream: () => stream.Readable,
-		getName: () => string,
-		getPath: () => ResourcePath,
-		getProject: () => Project,
-		getSourceMetadata: () => ResourceSourceMetadata
+		getBuffer: () => Promise;
+		getString: () => Promise;
+		getStream: () => stream.Readable;
+		getName: () => string;
+		getPath: () => ResourcePath;
+		getProject: () => Project;
+		getSourceMetadata: () => ResourceSourceMetadata;
 	}
 	enum ReaderStyles {
 		buildtime = "buildtime",
 		dist = "dist",
 		runtime = "runtime",
-		flat = "flat"
+		flat = "flat",
 	}
 	interface ReaderOptions {
-		style: ReaderStyles
+		style: ReaderStyles;
 	}
 	interface GlobOptions {
-		nodir?: boolean
+		nodir?: boolean;
 	}
 	interface AbstractReader {
-		byGlob: (virPattern: string | string[], options?: GlobOptions) => Promise
+		byGlob: (virPattern: string | string[], options?: GlobOptions) => Promise;
 	}
 	interface AbstractAdapter extends AbstractReader {
 
 	}
 }
 declare module "@ui5/fs/resourceFactory" {
-	export function createAdapter({fsBasePath: string, virBasePath: string}): AbstractAdapter
-	export function createResource({path: string, string: string}): Resource
+	export function createAdapter({fsBasePath: string, virBasePath: string}): AbstractAdapter;
+	export function createResource({path: string, string: string}): Resource;
 }
 
 declare module "@ui5/logger" {
 	interface Logger {
-		silly: (message: string) => void,
-		verbose: (message: string) => void,
-		perf: (message: string) => void,
-		info: (message: string) => void,
-		warn: (message: string) => void,
-		error: (message: string) => void,
-		isLevelEnabled: (level: string) => boolean,
+		silly: (message: string) => void;
+		verbose: (message: string) => void;
+		perf: (message: string) => void;
+		info: (message: string) => void;
+		warn: (message: string) => void;
+		error: (message: string) => void;
+		isLevelEnabled: (level: string) => boolean;
 	}
 
-	export function isLogLevelEnabled(logLevel: string): boolean
-	export function setLogLevel(logLevel: string): void
-	export function getLogLevel(logLevel: string): string
-	export function getLogger(moduleName: string): Logger
+	export function isLogLevelEnabled(logLevel: string): boolean;
+	export function setLogLevel(logLevel: string): void;
+	export function getLogLevel(logLevel: string): string;
+	export function getLogger(moduleName: string): Logger;
 }
 
 declare module "@ui5/logger/writers/Console" {
-	export function stop(): void
-	export function init(): void
+	export function stop(): void;
+	export function init(): void;
 }
 
 // There are no TS Types for json-source-map
diff --git a/test/lib/cli.ts b/test/lib/cli.ts
index 9dbc370d8..451b49ba9 100644
--- a/test/lib/cli.ts
+++ b/test/lib/cli.ts
@@ -1,30 +1,30 @@
-import anyTest, { TestFn } from "ava";
-import sinon, { SinonStub } from "sinon";
+import anyTest, {TestFn} from "ava";
+import sinon, {SinonStub} from "sinon";
 import yargs from "yargs";
-import esmock, { MockFunction } from "esmock";
+import esmock, {MockFunction} from "esmock";
 import {fileURLToPath} from "node:url";
 import {readFileSync} from "node:fs";
 
 const test = anyTest as TestFn<{
-	argvGetter: SinonStub,
+	argvGetter: SinonStub;
 	yargsInstance: yargs.Argv & {
-		parserConfiguration: SinonStub,
-		version: SinonStub,
-		scriptName: SinonStub,
-		command: SinonStub,
-		terminalWidth: SinonStub,
-		wrap: SinonStub,
-		argv: () => unknown
-	},
-	yargs: SinonStub,
-	setVersion: SinonStub,
-	cliBase: SinonStub,
-	readdir: SinonStub,
-	cli: MockFunction
+		parserConfiguration: SinonStub;
+		version: SinonStub;
+		scriptName: SinonStub;
+		command: SinonStub;
+		terminalWidth: SinonStub;
+		wrap: SinonStub;
+		argv: () => unknown;
+	};
+	yargs: SinonStub;
+	setVersion: SinonStub;
+	cliBase: SinonStub;
+	readdir: SinonStub;
+	cli: MockFunction;
 }>;
 
 const pkgJsonPath = new URL("../../package.json", import.meta.url);
-const pkg = JSON.parse(readFileSync(pkgJsonPath));
+const pkg = JSON.parse(((readFileSync(pkgJsonPath) as unknown) as string));
 
 test.beforeEach(async (t) => {
 	t.context.argvGetter = sinon.stub();
@@ -38,7 +38,7 @@ test.beforeEach(async (t) => {
 		get argv() {
 			t.context.argvGetter();
 			return undefined;
-		}
+		},
 	};
 
 	t.context.yargs = sinon.stub().returns(t.context.yargsInstance).named("yargs");
@@ -49,11 +49,11 @@ test.beforeEach(async (t) => {
 	t.context.cli = await esmock.p("../../src/cli.js", {
 		"yargs": t.context.yargs,
 		"../../src/cli/version.js": {
-			setVersion: t.context.setVersion
+			setVersion: t.context.setVersion,
 		},
 		"../../src/cli/base.js": t.context.cliBase,
 		"module": {
-			createRequire: sinon.stub().callsFake(() => sinon.stub().returns(pkg))
+			createRequire: sinon.stub().callsFake(() => sinon.stub().returns(pkg)),
 		},
 	});
 });
@@ -67,7 +67,7 @@ test.afterEach.always((t) => {
 test.serial("CLI", async (t) => {
 	const {
 		cli, argvGetter, yargsInstance, yargs,
-		setVersion, cliBase
+		setVersion, cliBase,
 	} = t.context;
 
 	await cli();
@@ -77,17 +77,17 @@ test.serial("CLI", async (t) => {
 
 	t.is(yargsInstance.parserConfiguration.callCount, 1);
 	t.deepEqual(yargsInstance.parserConfiguration.getCall(0).args, [{
-		"parse-numbers": false
+		"parse-numbers": false,
 	}]);
 
 	t.is(setVersion.callCount, 1);
 	t.deepEqual(setVersion.getCall(0).args, [
-		`${pkg.version} (from ${fileURLToPath(new URL("../../bin/ui5lint.js", import.meta.url))})`
+		`${pkg.version} (from ${fileURLToPath(new URL("../../bin/ui5lint.js", import.meta.url))})`,
 	]);
 
 	t.is(yargsInstance.version.callCount, 1);
 	t.deepEqual(yargsInstance.version.getCall(0).args, [
-		`${pkg.version} (from ${fileURLToPath(new URL("../../bin/ui5lint.js", import.meta.url))})`
+		`${pkg.version} (from ${fileURLToPath(new URL("../../bin/ui5lint.js", import.meta.url))})`,
 	]);
 
 	t.is(yargsInstance.scriptName.callCount, 1);
@@ -118,4 +118,4 @@ test.serial("CLI", async (t) => {
 		yargsInstance.wrap,
 		argvGetter
 	);
-});
\ No newline at end of file
+});
diff --git a/test/lib/cli/base.integration.ts b/test/lib/cli/base.integration.ts
index ef1941302..c82da948a 100644
--- a/test/lib/cli/base.integration.ts
+++ b/test/lib/cli/base.integration.ts
@@ -1,19 +1,19 @@
-import anyTest, { TestFn } from "ava";
-import sinon, { SinonStub } from "sinon";
+import anyTest, {TestFn} from "ava";
+import sinon, {SinonStub} from "sinon";
 import yargs from "yargs";
 import path from "node:path";
 import cliBase from "../../../src/cli/base.js";
-import { fileURLToPath } from "node:url";
-import { LintResult } from "../../../src/detectors/AbstractDetector.js";
+import {fileURLToPath} from "node:url";
+import {LintResult} from "../../../src/detectors/AbstractDetector.js";
 
 const __dirname = path.dirname(fileURLToPath(import.meta.url));
 const sampleProjectPath = path.join(__dirname, "..", "..", "fixtures", "linter", "projects", "com.ui5.troublesome.app");
 
 const test = anyTest as TestFn<{
-	consoleLogStub: SinonStub,
-    processCwdStub: SinonStub,
-	processStdoutWriteStub: SinonStub,
-	cli: yargs.Argv,
+	consoleLogStub: SinonStub;
+	processCwdStub: SinonStub;
+	processStdoutWriteStub: SinonStub;
+	cli: yargs.Argv;
 }>;
 
 test.beforeEach(async (t) => {
@@ -30,8 +30,8 @@ test.afterEach.always(() => {
 
 // Test if standard output is parsable JSON
 test.serial("ui5lint --format json", async (t) => {
-	const { cli } = t.context;
-	
+	const {cli} = t.context;
+
 	await cli.parseAsync(["--format", "json"]);
 
 	t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used");
@@ -40,7 +40,7 @@ test.serial("ui5lint --format json", async (t) => {
 
 	const resultProcessStdout = t.context.processStdoutWriteStub.firstCall.firstArg;
 	let parsedJson: LintResult[];
-	
+
 	t.notThrows(() => parsedJson = JSON.parse(resultProcessStdout), "Output of process.stdout.write is JSON-formatted");
 	t.true(Array.isArray(parsedJson!), "The parsed JSON output is a LintResult array");
 	t.true(parsedJson!.length > 0, "The parsed JSON output contains at least one result");
diff --git a/test/lib/cli/base.ts b/test/lib/cli/base.ts
index 294e1c5e1..4f44aa99f 100644
--- a/test/lib/cli/base.ts
+++ b/test/lib/cli/base.ts
@@ -1,24 +1,24 @@
-import anyTest, { TestFn } from "ava";
-import sinon, { SinonStub } from "sinon";
+import anyTest, {TestFn} from "ava";
+import sinon, {SinonStub} from "sinon";
 import esmock from "esmock";
 import chalk from "chalk";
 import yargs from "yargs";
 import path from "node:path";
-import type { LintResult } from "../../../src/detectors/AbstractDetector.js";
+import type {LintResult} from "../../../src/detectors/AbstractDetector.js";
 import type Base from "../../../src/cli/base.js";
 
 const test = anyTest as TestFn<{
-	lintProject: SinonStub,
-	writeFile: SinonStub,
-	consoleLogStub: SinonStub,
-	processStdErrWriteStub: SinonStub,
-	isLogLevelEnabledStub: SinonStub,
-	consoleWriterStopStub: SinonStub,
-	processErrWrite: SinonStub,
-	formatText: SinonStub,
-	formatJson: SinonStub,
-	cli: yargs.Argv,
-	base: typeof Base
+	lintProject: SinonStub;
+	writeFile: SinonStub;
+	consoleLogStub: SinonStub;
+	processStdErrWriteStub: SinonStub;
+	isLogLevelEnabledStub: SinonStub;
+	consoleWriterStopStub: SinonStub;
+	processErrWrite: SinonStub;
+	formatText: SinonStub;
+	formatJson: SinonStub;
+	cli: yargs.Argv;
+	base: typeof Base;
 }>;
 
 test.beforeEach(async (t) => {
@@ -48,32 +48,32 @@ test.beforeEach(async (t) => {
 
 	t.context.base = await esmock.p("../../../src/cli/base.js", {
 		"../../../src/linter/linter.js": {
-			lintProject: t.context.lintProject
+			lintProject: t.context.lintProject,
 		},
 		"../../../src/formatter/coverage.js": {
 			Coverage: sinon.stub().callsFake(() => {
-				return { format: sinon.stub().returns(null) };
-			})
+				return {format: sinon.stub().returns(null)};
+			}),
 		},
 		"../../../src/formatter/text.js": {
 			Text: sinon.stub().callsFake(() => {
-				return { format: t.context.formatText };
-			})
+				return {format: t.context.formatText};
+			}),
 		},
 		"../../../src/formatter/json.js": {
 			Json: sinon.stub().callsFake(() => {
-				return { format: t.context.formatJson };
-			})
+				return {format: t.context.formatJson};
+			}),
 		},
 		"node:fs/promises": {
-			writeFile: t.context.writeFile
+			writeFile: t.context.writeFile,
 		},
 		"@ui5/logger": {
-			isLogLevelEnabled: t.context.isLogLevelEnabledStub
+			isLogLevelEnabled: t.context.isLogLevelEnabledStub,
 		},
 		"@ui5/logger/writers/Console": {
-			stop: t.context.consoleWriterStopStub
-		}
+			stop: t.context.consoleWriterStopStub,
+		},
 	});
 
 	t.context.base(t.context.cli);
@@ -85,43 +85,43 @@ test.afterEach.always((t) => {
 });
 
 test.serial("ui5lint (default) ", async (t) => {
-	const { cli, lintProject, writeFile } = t.context;
+	const {cli, lintProject, writeFile} = t.context;
 
 	await cli.parseAsync([]);
 
 	t.true(lintProject.calledOnce, "Linter is called");
 	t.is(writeFile.callCount, 0, "Coverage was not called");
-	t.deepEqual(lintProject.getCall(0).args[0], { rootDir: path.join(process.cwd()), filePaths: undefined });
+	t.deepEqual(lintProject.getCall(0).args[0], {rootDir: path.join(process.cwd()), filePaths: undefined});
 	t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used");
 });
 
 test.serial("ui5lint --file-paths ", async (t) => {
-	const { cli, lintProject } = t.context;
+	const {cli, lintProject} = t.context;
 	const filePaths = [
 		path.resolve(process.cwd(), "path/to/resource"),
-		path.resolve(process.cwd(), "another/path/to/resource")
+		path.resolve(process.cwd(), "another/path/to/resource"),
 	];
 
 	await cli.parseAsync(["--file-paths", filePaths[0], "--file-paths", filePaths[1]]);
 
 	t.true(lintProject.calledOnce, "Linter is called");
-	t.deepEqual(lintProject.getCall(0).args[0], { rootDir: path.join(process.cwd()), filePaths });
+	t.deepEqual(lintProject.getCall(0).args[0], {rootDir: path.join(process.cwd()), filePaths});
 	t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used");
 });
 
 test.serial("ui5lint --coverage ", async (t) => {
-	const { cli, lintProject, writeFile } = t.context;
+	const {cli, lintProject, writeFile} = t.context;
 
 	await cli.parseAsync(["--coverage"]);
 
 	t.true(lintProject.calledOnce, "Linter is called");
 	t.is(writeFile.callCount, 1, "Coverage was called");
-	t.deepEqual(lintProject.getCall(0).args[0], { rootDir: path.join(process.cwd()), filePaths: undefined });
+	t.deepEqual(lintProject.getCall(0).args[0], {rootDir: path.join(process.cwd()), filePaths: undefined});
 	t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used");
 });
 
 test.serial("ui5lint --details ", async (t) => {
-	const { cli, lintProject, formatText } = t.context;
+	const {cli, lintProject, formatText} = t.context;
 
 	await cli.parseAsync(["--details"]);
 
@@ -131,7 +131,7 @@ test.serial("ui5lint --details ", async (t) => {
 });
 
 test.serial("ui5lint --format json ", async (t) => {
-	const { cli, lintProject, formatJson } = t.context;
+	const {cli, lintProject, formatJson} = t.context;
 
 	await cli.parseAsync(["--format", "json"]);
 
@@ -154,7 +154,7 @@ test.serial("Yargs error handling", async (t) => {
 	cli.command({
 		command: "foo",
 		describe: "This is a task",
-		handler: async function() {}
+		handler: async function () {},
 	});
 
 	await cli.parseAsync(["invalid"]);
@@ -165,12 +165,12 @@ test.serial("Yargs error handling", async (t) => {
 	t.is(consoleWriterStopStub.callCount, 0, "ConsoleWriter.stop did not get called");
 	t.is(processStdErrWriteStub.callCount, 5);
 	t.deepEqual(processStdErrWriteStub.getCall(0).args, [
-		chalk.bold.yellow("Command Failed:") + "\n"
+		chalk.bold.yellow("Command Failed:") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(1).args, ["Unknown argument: invalid\n"], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(2).args, ["\n"], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(3).args, [
-		chalk.dim(`See 'ui5lint --help'`) + "\n"
+		chalk.dim(`See 'ui5lint --help'`) + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(4).args, [""],
 		"Note: This is a call from handleLint as yargs doesn't really stop when process.exit is stubbed. " +
@@ -195,13 +195,13 @@ test.serial("Exception error handling", async (t) => {
 	cli.command({
 		command: "foo",
 		describe: "This task fails with an error",
-		handler: async function() {
+		handler: async function () {
 			throw error;
-		}
+		},
 	});
 
 	await t.throwsAsync(cli.parseAsync(["foo"]), {
-		is: error
+		is: error,
 	});
 
 	const errorCode = await processExit;
@@ -210,16 +210,16 @@ test.serial("Exception error handling", async (t) => {
 	t.is(consoleWriterStopStub.callCount, 1, "ConsoleWriter.stop got called once");
 	t.is(processStdErrWriteStub.callCount, 7);
 	t.deepEqual(processStdErrWriteStub.getCall(1).args, [
-		chalk.bold.red("⚠️  Process Failed With Error") + "\n"
+		chalk.bold.red("⚠️  Process Failed With Error") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(3).args, [
-		chalk.underline("Error Message:") + "\n"
+		chalk.underline("Error Message:") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(4).args,
 		["Some error from foo command\n"], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(6).args, [chalk.dim(
 		`For details, execute the same command again with an additional '--verbose' parameter`) +
-		"\n"
+		"\n",
 	], "Correct error log");
 	t.is(t.context.consoleLogStub.callCount, 0, "console.log should not be used");
 });
@@ -243,13 +243,13 @@ test.serial("Exception error handling without logging (silent)", async (t) => {
 	cli.command({
 		command: "foo",
 		describe: "This task fails with an error",
-		handler: async function() {
+		handler: async function () {
 			throw error;
-		}
+		},
 	});
 
 	await t.throwsAsync(cli.parseAsync(["foo"]), {
-		is: error
+		is: error,
 	});
 
 	const errorCode = await processExit;
@@ -279,13 +279,13 @@ test.serial("Exception error handling with verbose logging", async (t) => {
 	cli.command({
 		command: "foo",
 		describe: "This task fails with an error",
-		handler: async function() {
+		handler: async function () {
 			throw error;
-		}
+		},
 	});
 
 	await t.throwsAsync(cli.parseAsync(["foo"]), {
-		is: error
+		is: error,
 	});
 
 	const errorCode = await processExit;
@@ -293,10 +293,10 @@ test.serial("Exception error handling with verbose logging", async (t) => {
 	t.is(errorCode, 1, "Should exit with error code 1");
 	t.is(processStdErrWriteStub.callCount, 10);
 	t.deepEqual(processStdErrWriteStub.getCall(1).args, [
-		chalk.bold.red("⚠️  Process Failed With Error") + "\n"
+		chalk.bold.red("⚠️  Process Failed With Error") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(3).args, [
-		chalk.underline("Error Message:") + "\n"
+		chalk.underline("Error Message:") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(4).args,
 		["Some error from foo command\n"], "Correct error log");
@@ -331,13 +331,13 @@ test.serial("Unexpected error handling", async (t) => {
 	cli.command({
 		command: "foo",
 		describe: "This task fails with a TypeError",
-		handler: async function() {
+		handler: async function () {
 			throw typeError;
-		}
+		},
 	});
 
 	await t.throwsAsync(cli.parseAsync(["foo"]), {
-		is: typeError
+		is: typeError,
 	});
 
 	const errorCode = await processExit;
@@ -346,10 +346,10 @@ test.serial("Unexpected error handling", async (t) => {
 	t.is(consoleWriterStopStub.callCount, 1, "ConsoleWriter.stop got called once");
 	t.is(processStdErrWriteStub.callCount, 10);
 	t.deepEqual(processStdErrWriteStub.getCall(1).args, [
-		chalk.bold.red("⚠️  Process Failed With Error") + "\n"
+		chalk.bold.red("⚠️  Process Failed With Error") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(3).args, [
-		chalk.underline("Error Message:") + "\n"
+		chalk.underline("Error Message:") + "\n",
 	], "Correct error log");
 	t.deepEqual(processStdErrWriteStub.getCall(4).args,
 		["Cannot do this\n"], "Correct error log");
diff --git a/test/lib/cli/middlewares/base.ts b/test/lib/cli/middlewares/base.ts
index cd371d3cb..d47ba5d7d 100644
--- a/test/lib/cli/middlewares/base.ts
+++ b/test/lib/cli/middlewares/base.ts
@@ -1,18 +1,18 @@
 import anyTest, {TestFn} from "ava";
-import sinon, { SinonStub } from "sinon";
+import sinon, {SinonStub} from "sinon";
 import esmock from "esmock";
 
 const test = anyTest as TestFn<{
-	initLogger: SinonStub,
-	baseMiddleware: (args: { loglevel: number }) => void
+	initLogger: SinonStub;
+	baseMiddleware: (args: {loglevel: number}) => void;
 }>;
 
 test.beforeEach(async (t) => {
 	t.context.initLogger = sinon.stub();
 	t.context.baseMiddleware = await esmock("../../../../src/cli/middlewares/base.js", {
 		"../../../../src/cli/middlewares/logger.js": {
-			initLogger: t.context.initLogger
-		}
+			initLogger: t.context.initLogger,
+		},
 	});
 });
 
diff --git a/test/lib/cli/middlewares/logger.ts b/test/lib/cli/middlewares/logger.ts
index 03b4310bb..b7928bb8d 100644
--- a/test/lib/cli/middlewares/logger.ts
+++ b/test/lib/cli/middlewares/logger.ts
@@ -1,16 +1,16 @@
-import anyTest, { TestFn } from "ava";
+import anyTest, {TestFn} from "ava";
 import sinon, {SinonStub} from "sinon";
-import esmock, { MockFunction } from "esmock";
+import esmock, {MockFunction} from "esmock";
 
 const test = anyTest as TestFn<{
-	verboseLogStub: SinonStub,
-	setLogLevelStub: SinonStub,
-	isLogLevelEnabledStub: SinonStub,
-	getVersionStub: SinonStub,
+	verboseLogStub: SinonStub;
+	setLogLevelStub: SinonStub;
+	isLogLevelEnabledStub: SinonStub;
+	getVersionStub: SinonStub;
 	logger: MockFunction & {
-		initLogger: (args: 
-			{ loglevel?: string, verbose?: boolean, perf?: boolean, silent?: boolean }) => Promise | void
-	}
+		initLogger: (args:
+		{loglevel?: string; verbose?: boolean; perf?: boolean; silent?: boolean}) => Promise | void;
+	};
 }>;
 
 test.beforeEach(async (t) => {
@@ -20,7 +20,7 @@ test.beforeEach(async (t) => {
 	t.context.getVersionStub = sinon.stub().returns("1.0.0");
 	t.context.logger = await esmock("../../../../src/cli/middlewares/logger.js", {
 		"../../../../src/cli/version.js": {
-			getVersion: t.context.getVersionStub
+			getVersion: t.context.getVersionStub,
 		},
 		"@ui5/logger": {
 			getLogger: () => ({
@@ -28,12 +28,12 @@ test.beforeEach(async (t) => {
 			}),
 			setLogLevel: t.context.setLogLevelStub,
 			isLogLevelEnabled: t.context.isLogLevelEnabledStub,
-		}
+		},
 	});
 });
 
 test.serial("init logger", async (t) => {
-	const { logger, setLogLevelStub, isLogLevelEnabledStub, verboseLogStub, getVersionStub } = t.context;
+	const {logger, setLogLevelStub, isLogLevelEnabledStub, verboseLogStub, getVersionStub} = t.context;
 	await logger.initLogger({});
 	t.is(setLogLevelStub.callCount, 0, "setLevel has not been called");
 	t.is(isLogLevelEnabledStub.callCount, 1, "isLogLevelEnabled has been called once");
@@ -48,50 +48,50 @@ test.serial("init logger", async (t) => {
 });
 
 test.serial("With log-level flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ loglevel: "silly" });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({loglevel: "silly"});
 	t.is(setLogLevelStub.callCount, 1, "setLevel has been called once");
 	t.is(setLogLevelStub.getCall(0).args[0], "silly", "sets log level to silly");
 });
 
 test.serial("With default log-level flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ loglevel: "info" });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({loglevel: "info"});
 	t.is(setLogLevelStub.callCount, 0, "setLevel has not been called");
 });
 
 test.serial("With verbose flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ verbose: true });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({verbose: true});
 	t.is(setLogLevelStub.callCount, 1, "setLevel has been called once");
 	t.is(setLogLevelStub.getCall(0).args[0], "verbose", "sets log level to verbose");
 });
 
 test.serial("With perf flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ perf: true });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({perf: true});
 	t.is(setLogLevelStub.callCount, 1, "setLevel has been called once");
 	t.is(setLogLevelStub.getCall(0).args[0], "perf", "sets log level to perf");
 });
 
 test.serial("With silent flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ silent: true });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({silent: true});
 	t.is(setLogLevelStub.callCount, 1, "setLevel has been called once");
 	t.is(setLogLevelStub.getCall(0).args[0], "silent", "sets log level to silent");
 });
 
 test.serial("With log-level and verbose flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ loglevel: "silly", verbose: true });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({loglevel: "silly", verbose: true});
 	t.is(setLogLevelStub.callCount, 2, "setLevel has been called twice");
 	t.is(setLogLevelStub.getCall(0).args[0], "verbose", "sets log level to verbose");
 	t.is(setLogLevelStub.getCall(1).args[0], "silly", "sets log level to verbose");
 });
 
 test.serial("With log-level, verbose, perf and silent flag", async (t) => {
-	const { logger, setLogLevelStub } = t.context;
-	await logger.initLogger({ loglevel: "silly", verbose: true, perf: true, silent: true });
+	const {logger, setLogLevelStub} = t.context;
+	await logger.initLogger({loglevel: "silly", verbose: true, perf: true, silent: true});
 	t.is(setLogLevelStub.callCount, 4, "setLevel has been called four times");
 	t.is(setLogLevelStub.getCall(0).args[0], "silent", "sets log level to silent");
 	t.is(setLogLevelStub.getCall(1).args[0], "perf", "sets log level to perf");
diff --git a/test/lib/detectors/transpilers/amd/_helper.ts b/test/lib/detectors/transpilers/amd/_helper.ts
index d60690484..6bf17dcaa 100644
--- a/test/lib/detectors/transpilers/amd/_helper.ts
+++ b/test/lib/detectors/transpilers/amd/_helper.ts
@@ -6,10 +6,10 @@ import {readdirSync} from "node:fs";
 import fs from "node:fs/promises";
 import {amdToEsm} from "../../../../../src/detectors/transpilers/amd/transpiler.js";
 
-util.inspect.defaultOptions.depth = 4;  // Increase AVA's printing depth since coverageInfo objects are on level 4
+util.inspect.defaultOptions.depth = 4; // Increase AVA's printing depth since coverageInfo objects are on level 4
 
 const test = anyTest as TestFn<{
-	sinon: sinonGlobal.SinonSandbox,
+	sinon: sinonGlobal.SinonSandbox;
 }>;
 
 // Helper function to create linting tests for all files in a directory
@@ -43,7 +43,7 @@ export function createTestsForFixtures(fixturesPath: string) {
 				const fileContent = await fs.readFile(filePath);
 				const {source, map} = amdToEsm(testName, fileContent.toString(), true);
 				t.snapshot(source);
-				t.snapshot(map && JSON.parse(map));
+				t.snapshot(map && JSON.parse(map));
 			});
 		}
 	} catch (err) {
diff --git a/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts b/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts
index 89d0794a5..cd3749caf 100644
--- a/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts
+++ b/test/lib/detectors/transpilers/amd/parseModuleDeclaration.ts
@@ -4,17 +4,17 @@ import {ModuleDeclaration, DefineCallArgument, _matchArgumentsToParameters} from
 	"../../../../../src/detectors/transpilers/amd/parseModuleDeclaration.js";
 const {SyntaxKind} = ts;
 
-const test = anyTest as TestFn;
+const test = anyTest;
 
 test("All parameters provided directly", async (t) => {
 	const args = [{
-		kind: SyntaxKind.StringLiteral
+		kind: SyntaxKind.StringLiteral,
 	}, {
-		kind: SyntaxKind.ArrayLiteralExpression
+		kind: SyntaxKind.ArrayLiteralExpression,
 	}, {
-		kind: SyntaxKind.FunctionExpression
+		kind: SyntaxKind.FunctionExpression,
 	}, {
-		kind: SyntaxKind.TrueKeyword
+		kind: SyntaxKind.TrueKeyword,
 	}] as DefineCallArgument[];
 
 	t.deepEqual(_matchArgumentsToParameters(args), {
@@ -35,10 +35,9 @@ test("All parameters provided directly", async (t) => {
 
 test("Factory provided", async (t) => {
 	const args = [{
-		kind: SyntaxKind.FunctionExpression
+		kind: SyntaxKind.FunctionExpression,
 	}] as DefineCallArgument[];
 
-
 	t.deepEqual(_matchArgumentsToParameters(args), {
 		factory: {
 			kind: SyntaxKind.FunctionExpression,
@@ -48,12 +47,11 @@ test("Factory provided", async (t) => {
 
 test("Dependencies and Factory provided", async (t) => {
 	const args = [{
-		kind: SyntaxKind.ArrayLiteralExpression
+		kind: SyntaxKind.ArrayLiteralExpression,
 	}, {
-		kind: SyntaxKind.FunctionExpression
+		kind: SyntaxKind.FunctionExpression,
 	}] as DefineCallArgument[];
 
-
 	t.deepEqual(_matchArgumentsToParameters(args), {
 		dependencies: {
 			kind: SyntaxKind.ArrayLiteralExpression,
@@ -66,14 +64,13 @@ test("Dependencies and Factory provided", async (t) => {
 
 test("Module Name, Dependencies and Factory provided", async (t) => {
 	const args = [{
-		kind: SyntaxKind.StringLiteral
+		kind: SyntaxKind.StringLiteral,
 	}, {
-		kind: SyntaxKind.ArrayLiteralExpression
+		kind: SyntaxKind.ArrayLiteralExpression,
 	}, {
-		kind: SyntaxKind.FunctionExpression
+		kind: SyntaxKind.FunctionExpression,
 	}] as DefineCallArgument[];
 
-
 	t.deepEqual(_matchArgumentsToParameters(args), {
 		moduleName: {
 			kind: SyntaxKind.StringLiteral,
@@ -89,11 +86,11 @@ test("Module Name, Dependencies and Factory provided", async (t) => {
 
 test("Dependencies, Factory and Export provided", async (t) => {
 	const args = [{
-		kind: SyntaxKind.ArrayLiteralExpression
+		kind: SyntaxKind.ArrayLiteralExpression,
 	}, {
-		kind: SyntaxKind.FunctionExpression
+		kind: SyntaxKind.FunctionExpression,
 	}, {
-		kind: SyntaxKind.TrueKeyword
+		kind: SyntaxKind.TrueKeyword,
 	}] as DefineCallArgument[];
 
 	t.deepEqual(_matchArgumentsToParameters(args), {
@@ -110,11 +107,11 @@ test("Dependencies, Factory and Export provided", async (t) => {
 });
 
 interface TestArguments {
-	args: DefineCallArgument[],
-	expected: ModuleDeclaration,
+	args: DefineCallArgument[];
+	expected: ModuleDeclaration;
 }
 function generateArguments(possibleParameterTypes) {
-	const permutations: Array = [];
+	const permutations: TestArguments[] = [];
 	for (const moduleNameKind of possibleParameterTypes.moduleName) {
 		for (const dependenciesKind of possibleParameterTypes.dependencies) {
 			for (const factoryKind of possibleParameterTypes.factory) {
@@ -148,7 +145,6 @@ function generateArguments(possibleParameterTypes) {
 						expected.dependencies = factory as ModuleDeclaration["dependencies"];
 					}
 
-
 					if (factoryKind && expected.dependencies !== factory && expected.moduleName !== factory) {
 						expected.factory = factory;
 					} else if (exportKind) {
@@ -161,7 +157,7 @@ function generateArguments(possibleParameterTypes) {
 					const args = [moduleName, dependencies, factory, exp] as DefineCallArgument[];
 					permutations.push({
 						args,
-						expected: expected as ModuleDeclaration
+						expected: expected as ModuleDeclaration,
 					});
 				}
 			}
@@ -181,7 +177,7 @@ function resolveSyntaxKind(decl: ModuleDeclaration) {
 }
 
 function argsToString(args: DefineCallArgument[]): string {
-	return args.map(param => {
+	return args.map((param) => {
 		if (!param?.kind) {
 			return "";
 		}
@@ -196,20 +192,20 @@ function declToString(decl: ModuleDeclaration): string {
 
 test("All combinations", async (t) => {
 	const permutations = generateArguments({
-		moduleName: [SyntaxKind.StringLiteral, null /*implies omitted*/],
-		dependencies: [SyntaxKind.ArrayLiteralExpression, null /*implies omitted*/],
+		moduleName: [SyntaxKind.StringLiteral, null],
+		dependencies: [SyntaxKind.ArrayLiteralExpression, null],
 		factory: [
 			SyntaxKind.FunctionExpression, SyntaxKind.ArrowFunction,
 			SyntaxKind.StringLiteral, SyntaxKind.ArrayLiteralExpression,
-			SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword
+			SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword,
 		],
-		export: [SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, null /*implies omitted*/],
+		export: [SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, null],
 	});
 
 	t.true(permutations.length > 0, `Generated ${permutations.length} permutations`);
 	permutations.forEach(({args, expected}) => {
 		// Omit any parameters with "kind" set to null
-		const res = _matchArgumentsToParameters(args.filter(_ => _?.kind));
+		const res = _matchArgumentsToParameters(args.filter((_) => _?.kind));
 		t.deepEqual(
 			resolveSyntaxKind(res),
 			resolveSyntaxKind(expected),
diff --git a/test/lib/detectors/transpilers/amd/transpiler.ts b/test/lib/detectors/transpilers/amd/transpiler.ts
index c9d1c2a4f..3bd33ed42 100644
--- a/test/lib/detectors/transpilers/amd/transpiler.ts
+++ b/test/lib/detectors/transpilers/amd/transpiler.ts
@@ -10,8 +10,8 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
 const fixtures = path.join(__dirname, "..", "..", "..", "..", "fixtures", "transpiler", "amd");
 
 const test = anyTest as TestFn<{
-	sinon: sinonGlobal.SinonSandbox,
-	createdFiles: object,
+	sinon: sinonGlobal.SinonSandbox;
+	createdFiles: object;
 }>;
 
 test.beforeEach(async (t) => {
diff --git a/test/lib/detectors/transpilers/xml/_helper.ts b/test/lib/detectors/transpilers/xml/_helper.ts
index ab545a439..79fb92cc4 100644
--- a/test/lib/detectors/transpilers/xml/_helper.ts
+++ b/test/lib/detectors/transpilers/xml/_helper.ts
@@ -5,10 +5,10 @@ import util from "util";
 import fs from "node:fs";
 import {xmlToJs} from "../../../../../src/detectors/transpilers/xml/transpiler.js";
 
-util.inspect.defaultOptions.depth = 4;  // Increase AVA's printing depth since coverageInfo objects are on level 4
+util.inspect.defaultOptions.depth = 4; // Increase AVA's printing depth since coverageInfo objects are on level 4
 
 const test = anyTest as TestFn<{
-	sinon: sinonGlobal.SinonSandbox,
+	sinon: sinonGlobal.SinonSandbox;
 }>;
 
 // Helper function to create linting tests for all files in a directory
@@ -41,7 +41,7 @@ export function createTestsForFixtures(fixturesPath: string) {
 				const fileStream = fs.createReadStream(filePath);
 				const {source, map, messages} = await xmlToJs(testName, fileStream);
 				t.snapshot(source);
-				t.snapshot(map && JSON.parse(map));
+				t.snapshot(map && JSON.parse(map));
 				t.snapshot(messages);
 			});
 		}
diff --git a/test/lib/formatter/json.ts b/test/lib/formatter/json.ts
index 8ed9b12f7..6822964a7 100644
--- a/test/lib/formatter/json.ts
+++ b/test/lib/formatter/json.ts
@@ -1,6 +1,6 @@
-import anyTest, { TestFn } from "ava";
-import { Json } from "../../../src/formatter/json.ts";
-import { LintResult } from "../../../src/detectors/AbstractDetector.ts";
+import anyTest, {TestFn} from "ava";
+import {Json} from "../../../src/formatter/json.ts";
+import {LintResult} from "../../../src/detectors/AbstractDetector.ts";
 
 const test = anyTest as TestFn<{
 	lintResults: LintResult[];
@@ -15,8 +15,8 @@ test.beforeEach((t) => {
 			line: 5,
 			column: 1,
 			message: "Call to deprecated function 'attachInit' of class 'Core'",
-			messageDetails: "(since 1.118) - Please use {@link sap.ui.core.Core.ready Core.ready} instead."
-		},],
+			messageDetails: "(since 1.118) - Please use {@link sap.ui.core.Core.ready Core.ready} instead.",
+		}],
 		coverageInfo: [],
 		errorCount: 0,
 		fatalErrorCount: 0,
@@ -25,12 +25,12 @@ test.beforeEach((t) => {
 });
 
 test("Test Json Formatter (with '--details true')", (t) => {
-	const { lintResults } = t.context;
+	const {lintResults} = t.context;
 	const jsonFormatter = new Json();
 	const jsonResult = jsonFormatter.format(lintResults, true);
 	const parsedJson = JSON.parse(jsonResult); // fails if no valid JSON is returned
 
-	t.notDeepEqual(parsedJson,lintResults,
+	t.notDeepEqual(parsedJson, lintResults,
 		"Original lintResults and JSON-formatted ones have different structure");
 	t.true(Object.prototype.hasOwnProperty.call(parsedJson[0], "filePath"),
 		"The JSON-formatted lintResults contain the filePath property");
@@ -49,7 +49,7 @@ test("Test Json Formatter (with '--details true')", (t) => {
 });
 
 test("Test Json Formatter (with '--details false')", (t) => {
-	const { lintResults } = t.context;
+	const {lintResults} = t.context;
 	const jsonFormatter = new Json();
 	const jsonResult = jsonFormatter.format(lintResults, false);
 	const parsedJson = JSON.parse(jsonResult); // fails if no valid JSON is returned
diff --git a/test/lib/formatter/lib/resolveLinks.ts b/test/lib/formatter/lib/resolveLinks.ts
index d84536888..4a37e765a 100644
--- a/test/lib/formatter/lib/resolveLinks.ts
+++ b/test/lib/formatter/lib/resolveLinks.ts
@@ -1,7 +1,7 @@
-import anyTest, { TestFn } from "ava";
-import { resolveLinks } from "../../../../src/formatter/lib/resolveLinks.js";
+import anyTest, {TestFn} from "ava";
+import {resolveLinks} from "../../../../src/formatter/lib/resolveLinks.js";
 
-const test = anyTest as TestFn;
+const test = anyTest;
 
 test("Test links", (t) => {
 	const input = [
@@ -14,9 +14,9 @@ test("Test links", (t) => {
 		"(since 1.120) - Please use sap.ui.core.message.MessageType (https://ui5.sap.com/1.120/#/api/sap.ui.core.message.MessageType) instead.",
 		"(since 1.119) - Please use Lib.getResourceBundleFor  (https://ui5.sap.com/1.120/#/api/sap.ui.core.Lib)instead.",
 		"(since 1.118) - See Theming.attachApplied (https://ui5.sap.com/1.120/#/api/module:sap/ui/core/Theming%23methods/sap/ui/core/Theming.attachApplied)instead.",
-		"(since 1.56) - Use sap/ui/VersionInfo.load (https://ui5.sap.com/1.120/#/api/module:sap/ui/VersionInfo%23methods/sap/ui/VersionInfo.load) instead"
+		"(since 1.56) - Use sap/ui/VersionInfo.load (https://ui5.sap.com/1.120/#/api/module:sap/ui/VersionInfo%23methods/sap/ui/VersionInfo.load) instead",
 	];
-	
+
 	input.forEach((text, index) => {
 		t.is(resolveLinks(text), expected[index], "Correct resolution of links");
 	});
diff --git a/test/lib/linter/_linterHelper.ts b/test/lib/linter/_linterHelper.ts
index e5bc23f96..ad4527067 100644
--- a/test/lib/linter/_linterHelper.ts
+++ b/test/lib/linter/_linterHelper.ts
@@ -6,14 +6,14 @@ import esmock from "esmock";
 import {LintResult} from "../../../src/detectors/AbstractDetector.js";
 import FileLinter from "../../../src/detectors/typeChecker/FileLinter.ts";
 
-util.inspect.defaultOptions.depth = 4;  // Increase AVA's printing depth since coverageInfo objects are on level 4
+util.inspect.defaultOptions.depth = 4; // Increase AVA's printing depth since coverageInfo objects are on level 4
 
 const test = anyTest as TestFn<{
-	sinon: sinonGlobal.SinonSandbox,
-	lintFile: SinonStub
+	sinon: sinonGlobal.SinonSandbox;
+	lintFile: SinonStub;
 }>;
 
-test.before(async (t) => {	
+test.before(async (t) => {
 	const {lintModule: {lintFile}} = await esmockMessageDetails();
 	t.context.lintFile = lintFile;
 });
@@ -28,13 +28,13 @@ export async function esmockMessageDetails() {
 			const linter = new FileLinter(rootDir, filePath, sourceFile, sourceMap, checker);
 			linter.extractDeprecatedMessage = () => "Deprecated test message";
 			return linter;
-		}
+		},
 	});
-	
-	const lintModule =  await esmock("../../../src/linter/linter.js", {
-		"../../../src/detectors/typeChecker/index.js": checkerModule
+
+	const lintModule = await esmock("../../../src/linter/linter.js", {
+		"../../../src/detectors/typeChecker/index.js": checkerModule,
 	});
-	
+
 	return {lintModule, checkerModule};
 }
 
@@ -80,7 +80,7 @@ export function createTestsForFixtures(fixturesPath: string) {
 
 				const res = await lintFile({
 					rootDir: fixturesPath,
-					filePaths
+					filePaths,
 				});
 				assertExpectedLintResults(t, res, fixturesPath, filePaths);
 				res.forEach((results) => {
diff --git a/test/lib/linter/linter.ts b/test/lib/linter/linter.ts
index eca0d6abb..d489e58a3 100644
--- a/test/lib/linter/linter.ts
+++ b/test/lib/linter/linter.ts
@@ -10,13 +10,13 @@ const fixturesGeneralPath = path.join(fixturesBasePath, "general");
 const fixturesProjectsPath = path.join(fixturesBasePath, "projects");
 
 const test = anyTest as TestFn<{
-	sinon: sinonGlobal.SinonSandbox,
-	lintProject: SinonStub
+	sinon: sinonGlobal.SinonSandbox;
+	lintProject: SinonStub;
 }>;
 
 test.before(async (t) => {
 	t.context.sinon = sinonGlobal.createSandbox();
-	
+
 	const {lintModule: {lintProject}} = await esmockMessageDetails();
 	t.context.lintProject = lintProject;
 });
@@ -34,7 +34,7 @@ test.serial("lint: All files of com.ui5.troublesome.app", async (t) => {
 
 	let res = await lintProject({
 		rootDir: projectPath,
-		filePaths: []
+		filePaths: [],
 	});
 
 	res = res.sort((a, b) => {
@@ -55,7 +55,7 @@ test.serial("lint: Some files of com.ui5.troublesome.app", async (t) => {
 
 	let res = await lintProject({
 		rootDir: projectPath,
-		filePaths
+		filePaths,
 	});
 
 	res = res.sort((a, b) => {
@@ -64,7 +64,7 @@ test.serial("lint: Some files of com.ui5.troublesome.app", async (t) => {
 
 	assertExpectedLintResults(t, res, projectPath, [
 		path.join("webapp", "model", "models.js"),
-		...filePaths
+		...filePaths,
 	]);
 
 	t.snapshot(res);
@@ -76,7 +76,7 @@ test.serial("lint: All files of library.with.custom.paths", async (t) => {
 
 	let res = await lintProject({
 		rootDir: projectPath,
-		filePaths: []
+		filePaths: [],
 	});
 
 	res = res.sort((a, b) => {