renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
427 lines • 16.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setParseGradleFunc = setParseGradleFunc;
exports.handleAssignment = handleAssignment;
exports.handleDepString = handleDepString;
exports.handleKotlinShortNotationDep = handleKotlinShortNotationDep;
exports.handleLongFormDep = handleLongFormDep;
exports.handlePlugin = handlePlugin;
exports.handleRegistryContent = handleRegistryContent;
exports.handleRegistryUrl = handleRegistryUrl;
exports.handleLibraryDep = handleLibraryDep;
exports.handleApplyFrom = handleApplyFrom;
exports.handleImplicitDep = handleImplicitDep;
const tslib_1 = require("tslib");
const upath_1 = tslib_1.__importDefault(require("upath"));
const logger_1 = require("../../../../logger");
const fs_1 = require("../../../../util/fs");
const regex_1 = require("../../../../util/regex");
const url_1 = require("../../../../util/url");
const utils_1 = require("../utils");
const common_1 = require("./common");
// needed to break circular dependency
let parseGradle;
function setParseGradleFunc(func) {
parseGradle = func;
}
function handleAssignment(ctx) {
const key = (0, common_1.loadFromTokenMap)(ctx, 'keyToken')[0].value;
const valTokens = (0, common_1.loadFromTokenMap)(ctx, 'valToken');
if (valTokens.length > 1) {
// = template string with multiple variables
ctx.tokenMap.templateStringTokens = valTokens;
handleDepString(ctx);
delete ctx.tokenMap.templateStringTokens;
}
else if (valTokens[0].type === 'symbol') {
// foo = bar || foo = "${bar}"
const varData = (0, common_1.findVariable)(valTokens[0].value, ctx);
if (varData) {
ctx.globalVars[key] = { ...varData };
}
}
else {
// = string value
const dep = (0, utils_1.parseDependencyString)(valTokens[0].value);
if (dep) {
dep.sharedVariableName = key;
dep.managerData = {
fileReplacePosition: valTokens[0].offset + dep.depName.length + 1,
packageFile: ctx.packageFile,
};
ctx.deps.push(dep);
}
ctx.globalVars[key] = {
key,
value: valTokens[0].value,
fileReplacePosition: valTokens[0].offset,
packageFile: ctx.packageFile,
};
}
return ctx;
}
function handleDepString(ctx) {
const stringTokens = (0, common_1.loadFromTokenMap)(ctx, 'templateStringTokens');
const templateString = (0, common_1.interpolateString)(stringTokens, ctx);
if (!templateString) {
return ctx;
}
const dep = (0, utils_1.parseDependencyString)(templateString);
if (!dep) {
return ctx;
}
let packageFile;
let fileReplacePosition;
for (const token of stringTokens) {
if (token.type === 'symbol') {
const varData = (0, common_1.findVariable)(token.value, ctx);
if (varData) {
packageFile = varData.packageFile;
fileReplacePosition = varData.fileReplacePosition;
if (varData.value === dep.currentValue) {
dep.managerData = { fileReplacePosition, packageFile };
dep.sharedVariableName = varData.key;
}
}
}
}
if (!dep.managerData) {
const lastToken = stringTokens[stringTokens.length - 1];
if (lastToken?.type === 'string-value' &&
dep.currentValue &&
lastToken.value.includes(dep.currentValue)) {
packageFile = ctx.packageFile;
if (stringTokens.length === 1) {
fileReplacePosition = lastToken.offset + dep.depName.length + 1;
}
else {
fileReplacePosition =
lastToken.offset + lastToken.value.lastIndexOf(dep.currentValue);
}
delete dep.sharedVariableName;
}
else {
dep.skipReason = 'contains-variable';
}
dep.managerData = { fileReplacePosition, packageFile };
}
ctx.deps.push(dep);
return ctx;
}
function handleKotlinShortNotationDep(ctx) {
const moduleNameTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId');
const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version');
const moduleName = (0, common_1.interpolateString)(moduleNameTokens, ctx);
const versionValue = (0, common_1.interpolateString)(versionTokens, ctx);
if (!moduleName || !versionValue) {
return ctx;
}
const groupIdArtifactId = `org.jetbrains.kotlin:kotlin-${moduleName}`;
const dep = (0, utils_1.parseDependencyString)(`${groupIdArtifactId}:${versionValue}`);
if (!dep) {
return ctx;
}
dep.depName = moduleName;
dep.packageName = groupIdArtifactId;
dep.managerData = {
fileReplacePosition: versionTokens[0].offset,
packageFile: ctx.packageFile,
};
if (versionTokens.length > 1) {
// = template string with multiple variables
dep.skipReason = 'unspecified-version';
}
else if (versionTokens[0].type === 'symbol') {
const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx);
if (varData) {
dep.sharedVariableName = varData.key;
dep.currentValue = varData.value;
dep.managerData = {
fileReplacePosition: varData.fileReplacePosition,
packageFile: varData.packageFile,
};
}
}
ctx.deps.push(dep);
return ctx;
}
function handleLongFormDep(ctx) {
const groupIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'groupId');
const artifactIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId');
const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version');
const groupId = (0, common_1.interpolateString)(groupIdTokens, ctx);
const artifactId = (0, common_1.interpolateString)(artifactIdTokens, ctx);
const version = (0, common_1.interpolateString)(versionTokens, ctx);
if (!groupId || !artifactId || !version) {
return ctx;
}
// Special handling: 3 independent dependencies mismatched as groupId, artifactId, version
if ((0, utils_1.isDependencyString)(groupId) &&
(0, utils_1.isDependencyString)(artifactId) &&
(0, utils_1.isDependencyString)(version)) {
ctx.tokenMap.templateStringTokens = groupIdTokens;
handleDepString(ctx);
ctx.tokenMap.templateStringTokens = artifactIdTokens;
handleDepString(ctx);
ctx.tokenMap.templateStringTokens = versionTokens;
handleDepString(ctx);
return ctx;
}
const dep = (0, utils_1.parseDependencyString)([groupId, artifactId, version].join(':'));
if (!dep) {
return ctx;
}
const methodName = ctx.tokenMap.methodName ?? null;
if (versionTokens.length > 1) {
// = template string with multiple variables
dep.skipReason = 'unspecified-version';
}
else if (versionTokens[0].type === 'symbol') {
const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx);
if (varData) {
dep.sharedVariableName = varData.key;
dep.managerData = {
fileReplacePosition: varData.fileReplacePosition,
packageFile: varData.packageFile,
};
}
}
else {
// = string value
if (methodName?.[0]?.value === 'dependencySet') {
dep.sharedVariableName = `${groupId}:${version}`;
}
dep.managerData = {
fileReplacePosition: versionTokens[0].offset,
packageFile: ctx.packageFile,
};
}
ctx.deps.push(dep);
return ctx;
}
function handlePlugin(ctx) {
const methodName = (0, common_1.loadFromTokenMap)(ctx, 'methodName')[0];
const pluginName = (0, common_1.loadFromTokenMap)(ctx, 'pluginName')[0];
const pluginVersion = (0, common_1.loadFromTokenMap)(ctx, 'version');
const plugin = pluginName.value;
const depName = methodName.value === 'kotlin' ? `org.jetbrains.kotlin.${plugin}` : plugin;
const packageName = `${depName}:${depName}.gradle.plugin`;
const dep = {
depType: 'plugin',
depName,
packageName,
commitMessageTopic: `plugin ${depName}`,
currentValue: pluginVersion[0].value,
managerData: {
fileReplacePosition: pluginVersion[0].offset,
packageFile: ctx.packageFile,
},
};
if (pluginVersion.length > 1) {
// = template string with multiple variables
dep.skipReason = 'unspecified-version';
}
else if (pluginVersion[0].type === 'symbol') {
const varData = (0, common_1.findVariable)(pluginVersion[0].value, ctx);
if (varData) {
dep.sharedVariableName = varData.key;
dep.currentValue = varData.value;
dep.managerData = {
fileReplacePosition: varData.fileReplacePosition,
packageFile: varData.packageFile,
};
}
else {
dep.skipReason = 'unspecified-version';
}
}
ctx.deps.push(dep);
return ctx;
}
function isValidContentDescriptorRegex(fieldName, pattern) {
try {
(0, regex_1.regEx)(pattern);
}
catch {
logger_1.logger.debug(`Skipping content descriptor with unsupported regExp pattern for ${fieldName}: ${pattern}`);
return false;
}
return true;
}
function handleRegistryContent(ctx) {
const methodName = (0, common_1.loadFromTokenMap)(ctx, 'methodName')[0].value;
let groupId = (0, common_1.loadFromTokenMap)(ctx, 'groupId')[0].value;
let matcher = 'simple';
if (methodName.includes('Regex')) {
matcher = 'regex';
groupId = `^${groupId}$`.replaceAll('\\\\', '\\');
if (!isValidContentDescriptorRegex('group', groupId)) {
return ctx;
}
}
else if (methodName.includes('AndSubgroups')) {
matcher = 'subgroup';
}
const mode = methodName.startsWith('include') ? 'include' : 'exclude';
const spec = { mode, matcher, groupId };
if (methodName.includes('Module') || methodName.includes('Version')) {
spec.artifactId = (0, common_1.loadFromTokenMap)(ctx, 'artifactId')[0].value;
if (matcher === 'regex') {
spec.artifactId = `^${spec.artifactId}$`.replaceAll('\\\\', '\\');
if (!isValidContentDescriptorRegex('module', spec.artifactId)) {
return ctx;
}
}
}
if (methodName.includes('Version')) {
spec.version = (0, common_1.loadFromTokenMap)(ctx, 'version')[0].value;
if (matcher === 'regex') {
spec.version = `^${spec.version}$`.replaceAll('\\\\', '\\');
if (!isValidContentDescriptorRegex('version', spec.version)) {
return ctx;
}
}
}
ctx.tmpRegistryContent.push(spec);
return ctx;
}
function isPluginRegistry(ctx) {
if (ctx.tokenMap.registryScope) {
const registryScope = (0, common_1.loadFromTokenMap)(ctx, 'registryScope')[0].value;
return registryScope === 'pluginManagement';
}
return false;
}
function isExclusiveRegistry(ctx) {
if (ctx.tokenMap.registryType) {
const registryType = (0, common_1.loadFromTokenMap)(ctx, 'registryType')[0].value;
return registryType === 'exclusiveContent';
}
return false;
}
function handleRegistryUrl(ctx) {
let localVariables = ctx.globalVars;
if (ctx.tokenMap.name) {
const nameTokens = (0, common_1.loadFromTokenMap)(ctx, 'name');
const nameValue = (0, common_1.interpolateString)(nameTokens, ctx, localVariables);
if (nameValue) {
localVariables = {
...localVariables,
name: {
key: 'name',
value: nameValue,
},
};
}
}
let registryUrl = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'registryUrl'), ctx, localVariables);
if (registryUrl) {
registryUrl = registryUrl.replace((0, regex_1.regEx)(/\\/g), '');
const url = (0, url_1.parseUrl)(registryUrl);
if (url?.host && url.protocol) {
ctx.registryUrls.push({
registryUrl,
registryType: isExclusiveRegistry(ctx) ? 'exclusive' : 'regular',
scope: isPluginRegistry(ctx) ? 'plugin' : 'dep',
content: ctx.tmpRegistryContent,
});
}
}
return ctx;
}
function handleLibraryDep(ctx) {
const groupIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'groupId');
const artifactIdTokens = (0, common_1.loadFromTokenMap)(ctx, 'artifactId');
const groupId = (0, common_1.interpolateString)(groupIdTokens, ctx);
const artifactId = (0, common_1.interpolateString)(artifactIdTokens, ctx);
if (!groupId || !artifactId) {
return ctx;
}
const aliasToken = (0, common_1.loadFromTokenMap)(ctx, 'alias')[0];
const key = `libs.${aliasToken.value.replace((0, regex_1.regEx)(/[-_]/g), '.')}`;
ctx.globalVars[key] = {
key,
value: `${groupId}:${artifactId}`,
fileReplacePosition: aliasToken.offset,
packageFile: ctx.packageFile,
};
if (ctx.tokenMap.version) {
const version = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'version'), ctx);
if (version) {
handleLongFormDep(ctx);
}
}
return ctx;
}
function handleApplyFrom(ctx) {
let scriptFile = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'scriptFile'), ctx);
if (!scriptFile) {
return ctx;
}
if (ctx.tokenMap.parentPath) {
const parentPath = (0, common_1.interpolateString)((0, common_1.loadFromTokenMap)(ctx, 'parentPath'), ctx);
if (parentPath && scriptFile) {
scriptFile = upath_1.default.join(parentPath, scriptFile);
}
}
if (ctx.recursionDepth > 2) {
logger_1.logger.debug(`Max recursion depth reached in script file: ${scriptFile}`);
return ctx;
}
if (!(0, regex_1.regEx)(/\.gradle(\.kts)?$/).test(scriptFile)) {
logger_1.logger.debug({ scriptFile }, `Only Gradle files can be included`);
return ctx;
}
const scriptFilePath = (0, fs_1.getSiblingFileName)(ctx.packageFile, scriptFile);
if (!ctx.fileContents[scriptFilePath]) {
logger_1.logger.debug(`Failed to process included Gradle file ${scriptFilePath}`);
return ctx;
}
const matchResult = parseGradle(
// TODO #22198
ctx.fileContents[scriptFilePath], ctx.globalVars, scriptFilePath, ctx.fileContents, ctx.recursionDepth + 1);
ctx.deps.push(...matchResult.deps);
ctx.globalVars = { ...ctx.globalVars, ...matchResult.vars };
ctx.registryUrls.push(...matchResult.urls);
return ctx;
}
function handleImplicitDep(ctx) {
const implicitDepName = (0, common_1.loadFromTokenMap)(ctx, 'implicitDepName')[0].value;
const versionTokens = (0, common_1.loadFromTokenMap)(ctx, 'version');
const versionValue = (0, common_1.interpolateString)(versionTokens, ctx);
if (!versionValue) {
return ctx;
}
const isImplicitGradlePlugin = implicitDepName in common_1.GRADLE_PLUGINS;
const groupIdArtifactId = isImplicitGradlePlugin
? common_1.GRADLE_PLUGINS[implicitDepName][1]
: common_1.GRADLE_TEST_SUITES[implicitDepName];
const dep = (0, utils_1.parseDependencyString)(`${groupIdArtifactId}:${versionValue}`);
if (!dep) {
return ctx;
}
dep.depName = implicitDepName;
dep.packageName = groupIdArtifactId;
dep.managerData = {
fileReplacePosition: versionTokens[0].offset,
packageFile: ctx.packageFile,
};
if (versionTokens.length > 1) {
// = template string with multiple variables
dep.skipReason = 'unspecified-version';
}
else if (versionTokens[0].type === 'symbol') {
const varData = (0, common_1.findVariable)(versionTokens[0].value, ctx);
if (varData) {
dep.sharedVariableName = varData.key;
dep.currentValue = varData.value;
dep.managerData = {
fileReplacePosition: varData.fileReplacePosition,
packageFile: varData.packageFile,
};
}
}
ctx.deps.push(dep);
return ctx;
}
//# sourceMappingURL=handlers.js.map