Files
Sebastian Poxhofer 9717259ffc refactor(oxlint): enable no-else-return and unicorn/no-lonely-if (#44553)
Enable no-else-return (with allowElseIf: false) and unicorn/no-lonely-if
as errors in .oxlintrc.json and fix all 131 pre-existing violations
(91 no-else-return, 40 unicorn/no-lonely-if) across 98 files.

The no-else-return violations were fixed with the oxlint autofix
(iterated to a fixpoint, plus two else-if chains that required
--fix-dangerously) followed by Prettier formatting. One comment dropped
by the autofix in lib/modules/manager/pub/artifacts.ts was restored
manually. The unicorn/no-lonely-if violations were merged by hand,
preserving comments and coverage-ignore hints.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 12:11:21 +00:00

182 lines
5.0 KiB
TypeScript

import { isString } from '@sindresorhus/is';
import { miscUtils, structUtils } from '@yarnpkg/core';
import { parseSyml } from '@yarnpkg/parsers';
import { logger } from '../../../../logger/index.ts';
import {
getSiblingFileName,
localPathExists,
readLocalFile,
} from '../../../../util/fs/index.ts';
import type { PackageFileContent } from '../../types.ts';
import type { YarnCatalogs } from '../schema.ts';
import type { NpmManagerData } from '../types.ts';
import { extractCatalogDeps } from './common/catalogs.ts';
import type { Catalog, LockFile } from './types.ts';
export async function getYarnLock(filePath: string): Promise<LockFile> {
// TODO #22198
const yarnLockRaw = (await readLocalFile(filePath, 'utf8'))!;
try {
const parsed = parseSyml(yarnLockRaw);
const lockedVersions: Record<string, string> = {};
let lockfileVersion: number | undefined;
for (const [key, val] of Object.entries(parsed)) {
if (key === '__metadata') {
// yarn 2
lockfileVersion = parseInt(val.cacheKey, 10);
logger.once.debug(
`yarn.lock ${filePath} has __metadata.cacheKey=${lockfileVersion}`,
);
} else {
for (const entry of key.split(', ')) {
try {
const { scope, name, range } = structUtils.parseDescriptor(entry);
const packageName = scope ? `@${scope}/${name}` : name;
const { selector } = structUtils.parseRange(range);
logger.trace({ entry, version: val.version });
lockedVersions[`${packageName}@${selector}`] = parsed[key].version;
} catch (err) {
logger.debug(
{ entry, err },
'Invalid descriptor or range found in yarn.lock',
);
}
}
}
}
const isYarn1 = !('__metadata' in parsed);
if (isYarn1) {
logger.once.debug(
`yarn.lock ${filePath} is has no __metadata so is yarn 1`,
);
} else {
logger.once.debug(
`yarn.lock ${filePath} is has __metadata so is yarn 2+`,
);
}
return {
isYarn1,
lockfileVersion,
lockedVersions,
};
} catch (err) {
logger.debug({ filePath, err }, 'Warning: Exception parsing yarn.lock');
return { isYarn1: true, lockedVersions: {} };
}
}
export function getZeroInstallPaths(yarnrcYml: string): string[] {
// TODO: fix type #22198
let conf: any;
try {
conf = parseSyml(yarnrcYml);
} catch (err) /* v8 ignore next -- TODO: add test #40625 */ {
logger.warn({ err }, 'Error parsing .yarnrc.yml');
}
const paths = [
conf?.cacheFolder ?? './.yarn/cache',
'.pnp.cjs',
'.pnp.js',
'.pnp.loader.mjs',
];
if (
conf &&
miscUtils.tryParseOptionalBoolean(conf.pnpEnableInlining) === false
) {
paths.push(conf.pnpDataPath ?? './.pnp.data.json');
}
return paths;
}
export async function isZeroInstall(yarnrcYmlPath: string): Promise<boolean> {
const yarnrcYml = await readLocalFile(yarnrcYmlPath, 'utf8');
// v8 ignore else -- TODO: add test #40625
if (isString(yarnrcYml)) {
const paths = getZeroInstallPaths(yarnrcYml);
for (const p of paths) {
if (await localPathExists(getSiblingFileName(yarnrcYmlPath, p))) {
logger.debug(`Detected Yarn zero-install in ${p}`);
return true;
}
}
}
return false;
}
export function getYarnVersionFromLock(lockfile: LockFile): string {
const { lockfileVersion, isYarn1 } = lockfile;
if (isYarn1) {
return '^1.22.18';
}
if (lockfileVersion && lockfileVersion >= 12) {
// This will probably be v5
return '>=4.0.0';
}
if (lockfileVersion && lockfileVersion >= 10) {
return '^4.0.0';
}
if (lockfileVersion && lockfileVersion >= 8) {
// https://github.com/yarnpkg/berry/commit/9bcd27ae34aee77a567dd104947407532fa179b3
return '^3.0.0';
}
if (lockfileVersion && lockfileVersion >= 6) {
// https://github.com/yarnpkg/berry/commit/f753790380cbda5b55d028ea84b199445129f9ba
return '^2.2.0';
}
return '^2.0.0';
}
export async function extractYarnCatalogs(
catalogs: YarnCatalogs,
packageFile: string,
hasPackageManager: boolean,
): Promise<PackageFileContent<NpmManagerData>> {
logger.trace(`yarn.extractYarnCatalogs(${packageFile})`);
const yarnCatalogs = yarnCatalogsToArray(catalogs);
const deps = extractCatalogDeps(yarnCatalogs, 'yarn');
let yarnLock: string | undefined;
const filePath = getSiblingFileName(packageFile, 'yarn.lock');
if (await localPathExists(filePath)) {
yarnLock = filePath;
}
return {
deps,
managerData: {
yarnLock,
hasPackageManager,
},
};
}
function yarnCatalogsToArray({
catalog: defaultCatalogDeps,
catalogs: namedCatalogs,
}: YarnCatalogs): Catalog[] {
const result: Catalog[] = [];
if (defaultCatalogDeps !== undefined) {
result.push({ name: 'default', dependencies: defaultCatalogDeps });
}
if (!namedCatalogs) {
return result;
}
for (const [name, dependencies] of Object.entries(namedCatalogs)) {
result.push({
name,
dependencies,
});
}
return result;
}