UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

361 lines (360 loc) • 13.1 kB
import { regEx } from "../../../../util/regex.js"; import { logger } from "../../../../logger/index.js"; import { parseUrl } from "../../../../util/url.js"; import { getSiblingFileName } from "../../../../util/fs/index.js"; import { GRADLE_PLUGINS, GRADLE_TEST_SUITES, findVariable, interpolateString, loadFromTokenMap } from "./common.js"; import { isDependencyString, parseDependencyString } from "../utils.js"; import upath from "upath"; //#region lib/modules/manager/gradle/parser/handlers.ts let parseGradle; function setParseGradleFunc(func) { parseGradle = func; } function handleAssignment(ctx) { const key = loadFromTokenMap(ctx, "keyToken")[0].value; const valTokens = loadFromTokenMap(ctx, "valToken"); if (valTokens.length > 1) { ctx.tokenMap.templateStringTokens = valTokens; handleDepString(ctx); delete ctx.tokenMap.templateStringTokens; } else if (valTokens[0].type === "symbol") { const varData = findVariable(valTokens[0].value, ctx); if (varData) ctx.globalVars[key] = { ...varData }; } else { const dep = 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 = loadFromTokenMap(ctx, "templateStringTokens"); const templateString = interpolateString(stringTokens, ctx); if (!templateString) return ctx; const dep = parseDependencyString(templateString); if (!dep) return ctx; let packageFile; let fileReplacePosition; for (const token of stringTokens) if (token.type === "symbol") { const varData = 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 = loadFromTokenMap(ctx, "artifactId"); const versionTokens = loadFromTokenMap(ctx, "version"); const moduleName = interpolateString(moduleNameTokens, ctx); const versionValue = interpolateString(versionTokens, ctx); if (!moduleName || !versionValue) return ctx; const groupIdArtifactId = `org.jetbrains.kotlin:kotlin-${moduleName}`; const dep = 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) dep.skipReason = "unspecified-version"; else if (versionTokens[0].type === "symbol") { const varData = 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 = loadFromTokenMap(ctx, "groupId"); const artifactIdTokens = loadFromTokenMap(ctx, "artifactId"); const versionTokens = loadFromTokenMap(ctx, "version"); const groupId = interpolateString(groupIdTokens, ctx); const artifactId = interpolateString(artifactIdTokens, ctx); const version = interpolateString(versionTokens, ctx); if (!groupId || !artifactId || !version) return ctx; if (isDependencyString(groupId) && isDependencyString(artifactId) && isDependencyString(version)) { ctx.tokenMap.templateStringTokens = groupIdTokens; handleDepString(ctx); ctx.tokenMap.templateStringTokens = artifactIdTokens; handleDepString(ctx); ctx.tokenMap.templateStringTokens = versionTokens; handleDepString(ctx); return ctx; } const dep = parseDependencyString([ groupId, artifactId, version ].join(":")); if (!dep) return ctx; const methodName = ctx.tokenMap.methodName ?? null; if (versionTokens.length > 1) dep.skipReason = "unspecified-version"; else if (versionTokens[0].type === "symbol") { const varData = findVariable(versionTokens[0].value, ctx); if (varData) { dep.sharedVariableName = varData.key; dep.managerData = { fileReplacePosition: varData.fileReplacePosition, packageFile: varData.packageFile }; } } else { 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 = loadFromTokenMap(ctx, "methodName")[0]; const pluginNameTokens = loadFromTokenMap(ctx, "pluginName"); const pluginVersion = loadFromTokenMap(ctx, "version"); const plugin = interpolateString(pluginNameTokens, ctx); if (!plugin) return ctx; const depName = methodName.value === "kotlin" ? `org.jetbrains.kotlin.${plugin}` : plugin; const dep = { depType: "plugin", depName, packageName: `${depName}:${depName}.gradle.plugin`, commitMessageTopic: `plugin ${depName}`, currentValue: pluginVersion[0].value, managerData: { fileReplacePosition: pluginVersion[0].offset, packageFile: ctx.packageFile } }; if (pluginVersion.length > 1) dep.skipReason = "unspecified-version"; else if (pluginVersion[0].type === "symbol") { const varData = 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 { regEx(pattern); } catch { logger.debug(`Skipping content descriptor with unsupported regExp pattern for ${fieldName}: ${pattern}`); return false; } return true; } function handleRegistryContent(ctx) { const methodName = loadFromTokenMap(ctx, "methodName")[0].value; let groupId = 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 spec = { mode: methodName.startsWith("include") ? "include" : "exclude", matcher, groupId }; if (methodName.includes("Module") || methodName.includes("Version")) { spec.artifactId = 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 = 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) return loadFromTokenMap(ctx, "registryScope")[0].value === "pluginManagement"; return false; } function isExclusiveRegistry(ctx) { if (ctx.tokenMap.registryType) return loadFromTokenMap(ctx, "registryType")[0].value === "exclusiveContent"; return false; } function handleRegistryUrl(ctx) { let localVariables = ctx.globalVars; if (!ctx.tokenMap.registryUrl) return ctx; if (ctx.tokenMap.name) { const nameValue = interpolateString(loadFromTokenMap(ctx, "name"), ctx, localVariables); if (nameValue) localVariables = { ...localVariables, name: { key: "name", value: nameValue } }; } let registryUrl = interpolateString(loadFromTokenMap(ctx, "registryUrl"), ctx, localVariables); if (registryUrl) { registryUrl = registryUrl.replace(regEx(/\\/g), ""); const url = parseUrl(registryUrl); if (url?.host && url.protocol) { const registryType = isExclusiveRegistry(ctx) ? "exclusive" : "regular"; if (registryType === "exclusive" && !ctx.tmpRegistryContent.length) { logger.debug(`Skipping exclusive registry ${registryUrl} with unsupported content descriptors`); return ctx; } ctx.registryUrls.push({ registryUrl, registryType, scope: isPluginRegistry(ctx) ? "plugin" : "dep", content: ctx.tmpRegistryContent }); } } return ctx; } function handleCatalogLongFormDep(ctx) { const groupIdTokens = loadFromTokenMap(ctx, "groupId"); const artifactIdTokens = loadFromTokenMap(ctx, "artifactId"); const groupId = interpolateString(groupIdTokens, ctx); const artifactId = interpolateString(artifactIdTokens, ctx); if (!groupId || !artifactId) return ctx; const aliasToken = loadFromTokenMap(ctx, "alias")[0]; const key = `libs.${aliasToken.value.replace(regEx(/[-_]/g), ".")}`; ctx.globalVars[key] = { key, value: `${groupId}:${artifactId}`, fileReplacePosition: aliasToken.offset, packageFile: ctx.packageFile }; if (ctx.tokenMap.version) { if (interpolateString(loadFromTokenMap(ctx, "version"), ctx)) handleLongFormDep(ctx); } return ctx; } function handleCatalogDepString(ctx) { const templateString = interpolateString(loadFromTokenMap(ctx, "templateStringTokens"), ctx); if (!templateString) return ctx; const aliasToken = loadFromTokenMap(ctx, "alias")[0]; const key = `libs.${aliasToken.value.replace(regEx(/[-_]/g), ".")}`; ctx.globalVars[key] = { key, value: templateString, fileReplacePosition: aliasToken.offset, packageFile: ctx.packageFile }; return handleDepString(ctx); } function handleApplyFrom(ctx) { let scriptFile = interpolateString(loadFromTokenMap(ctx, "scriptFile"), ctx); if (!scriptFile) return ctx; if (ctx.tokenMap.parentPath) { const parentPath = interpolateString(loadFromTokenMap(ctx, "parentPath"), ctx); if (parentPath && scriptFile) scriptFile = upath.join(parentPath, scriptFile); } if (ctx.recursionDepth > 2) { logger.debug(`Max recursion depth reached in script file: ${scriptFile}`); return ctx; } if (!regEx(/\.gradle(\.kts)?$/).test(scriptFile)) { logger.debug({ scriptFile }, `Only Gradle files can be included`); return ctx; } const scriptFilePath = getSiblingFileName(ctx.packageFile, scriptFile); if (!ctx.fileContents[scriptFilePath]) { logger.debug(`Failed to process included Gradle file ${scriptFilePath}`); return ctx; } const matchResult = parseGradle(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 = loadFromTokenMap(ctx, "implicitDepName")[0].value; const versionTokens = loadFromTokenMap(ctx, "version"); const versionValue = interpolateString(versionTokens, ctx); if (!versionValue) return ctx; const groupIdArtifactId = implicitDepName in GRADLE_PLUGINS ? GRADLE_PLUGINS[implicitDepName][1] : GRADLE_TEST_SUITES[implicitDepName]; const dep = 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) dep.skipReason = "unspecified-version"; else if (versionTokens[0].type === "symbol") { const varData = 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; } //#endregion export { handleApplyFrom, handleAssignment, handleCatalogDepString, handleCatalogLongFormDep, handleDepString, handleImplicitDep, handleKotlinShortNotationDep, handleLongFormDep, handlePlugin, handleRegistryContent, handleRegistryUrl, setParseGradleFunc }; //# sourceMappingURL=handlers.js.map