Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(gradle/manager): introduce method to resolve variables #21531

Merged
merged 1 commit into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions lib/modules/manager/gradle/parser/common.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { lexer } from 'good-enough-parser';
import { partial } from '../../../../../test/util';
import type { Ctx, PackageVariables } from '../types';
import type { Ctx } from '../types';
import {
cleanupTempVars,
coalesceVariable,
findVariable,
increaseNestingDepth,
interpolateString,
loadFromTokenMap,
Expand Down Expand Up @@ -112,15 +113,25 @@ describe('modules/manager/gradle/parser/common', () => {
expect(ctx.varTokens).toStrictEqual([{ value: 'foo.bar.baz.qux' }]);
});

it('findVariable', () => {
ctx.globalVars = {
foo: { key: 'foo', value: 'bar' },
};

expect(findVariable('unknown-global-var', ctx)).toBeUndefined();
expect(findVariable('foo', ctx)).toStrictEqual(ctx.globalVars['foo']);
});

it('interpolateString', () => {
expect(interpolateString([], {})).toBeEmptyString();
expect(interpolateString([], ctx)).toBeEmptyString();
expect(
interpolateString(
partial<lexer.Token>([
{ type: 'string-value', value: 'foo' },
{ type: 'symbol', value: 'bar' },
{ type: 'string-value', value: 'baz' },
]),
ctx,
{
bar: { key: '', value: 'BAR' },
}
Expand All @@ -129,13 +140,13 @@ describe('modules/manager/gradle/parser/common', () => {
expect(
interpolateString(
partial<lexer.Token>([{ type: 'symbol', value: 'foo' }]),
partial<PackageVariables>()
ctx
)
).toBeNull();
expect(
interpolateString(
partial<lexer.Token>([{ type: '_', value: 'foo' }]),
partial<PackageVariables>()
ctx
)
).toBeNull();
});
Expand Down
20 changes: 17 additions & 3 deletions lib/modules/manager/gradle/parser/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { lexer, parser, query as q } from 'good-enough-parser';
import { clone } from '../../../../util/clone';
import { regEx } from '../../../../util/regex';
import type { Ctx, NonEmptyArray, PackageVariables } from '../types';
import type {
Ctx,
NonEmptyArray,
PackageVariables,
VariableData,
} from '../types';

export const REGISTRY_URLS = {
google: 'https://dl.google.com/android/maven2/',
Expand Down Expand Up @@ -114,17 +119,26 @@ export function coalesceVariable(ctx: Ctx): Ctx {
return ctx;
}

export function findVariable(
name: string,
ctx: Ctx,
variables: PackageVariables = ctx.globalVars
): VariableData | undefined {
return variables[name];
}

export function interpolateString(
childTokens: lexer.Token[],
variables: PackageVariables
ctx: Ctx,
variables: PackageVariables = ctx.globalVars
): string | null {
const resolvedSubstrings: string[] = [];
for (const childToken of childTokens) {
const type = childToken.type;
if (type === 'string-value') {
resolvedSubstrings.push(childToken.value);
} else if (type === 'symbol') {
const varData = variables[childToken.value];
const varData = findVariable(childToken.value, ctx, variables);
if (varData) {
resolvedSubstrings.push(varData.value);
} else {
Expand Down
46 changes: 21 additions & 25 deletions lib/modules/manager/gradle/parser/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ANNOYING_METHODS,
GRADLE_PLUGINS,
REGISTRY_URLS,
findVariable,
interpolateString,
loadFromTokenMap,
} from './common';
Expand All @@ -32,7 +33,7 @@ export function handleAssignment(ctx: Ctx): Ctx {
delete ctx.tokenMap.templateStringTokens;
} else if (valTokens[0].type === 'symbol') {
// foo = bar || foo = "${bar}"
const varData = ctx.globalVars[valTokens[0].value];
const varData = findVariable(valTokens[0].value, ctx);
if (varData) {
ctx.globalVars[key] = { ...varData };
}
Expand Down Expand Up @@ -62,7 +63,7 @@ export function handleAssignment(ctx: Ctx): Ctx {
export function handleDepString(ctx: Ctx): Ctx {
const stringTokens = loadFromTokenMap(ctx, 'templateStringTokens');

const templateString = interpolateString(stringTokens, ctx.globalVars);
const templateString = interpolateString(stringTokens, ctx);
if (!templateString) {
return ctx;
}
Expand All @@ -76,7 +77,7 @@ export function handleDepString(ctx: Ctx): Ctx {
let fileReplacePosition: number | undefined;
for (const token of stringTokens) {
if (token.type === 'symbol') {
const varData = ctx.globalVars[token.value];
const varData = findVariable(token.value, ctx);
if (varData) {
packageFile = varData.packageFile;
fileReplacePosition = varData.fileReplacePosition;
Expand Down Expand Up @@ -118,8 +119,8 @@ export function handleKotlinShortNotationDep(ctx: Ctx): Ctx {
const moduleNameTokens = loadFromTokenMap(ctx, 'artifactId');
const versionTokens = loadFromTokenMap(ctx, 'version');

const moduleName = interpolateString(moduleNameTokens, ctx.globalVars);
const versionValue = interpolateString(versionTokens, ctx.globalVars);
const moduleName = interpolateString(moduleNameTokens, ctx);
const versionValue = interpolateString(versionTokens, ctx);
if (!moduleName || !versionValue) {
return ctx;
}
Expand All @@ -141,7 +142,7 @@ export function handleKotlinShortNotationDep(ctx: Ctx): Ctx {
// = template string with multiple variables
dep.skipReason = 'unknown-version';
} else if (versionTokens[0].type === 'symbol') {
const varData = ctx.globalVars[versionTokens[0].value];
const varData = findVariable(versionTokens[0].value, ctx);
if (varData) {
dep.groupName = varData.key;
dep.currentValue = varData.value;
Expand All @@ -162,9 +163,9 @@ export function handleLongFormDep(ctx: Ctx): Ctx {
const artifactIdTokens = loadFromTokenMap(ctx, 'artifactId');
const versionTokens = loadFromTokenMap(ctx, 'version');

const groupId = interpolateString(groupIdTokens, ctx.globalVars);
const artifactId = interpolateString(artifactIdTokens, ctx.globalVars);
const version = interpolateString(versionTokens, ctx.globalVars);
const groupId = interpolateString(groupIdTokens, ctx);
const artifactId = interpolateString(artifactIdTokens, ctx);
const version = interpolateString(versionTokens, ctx);
if (!groupId || !artifactId || !version) {
return ctx;
}
Expand All @@ -179,7 +180,7 @@ export function handleLongFormDep(ctx: Ctx): Ctx {
// = template string with multiple variables
dep.skipReason = 'unknown-version';
} else if (versionTokens[0].type === 'symbol') {
const varData = ctx.globalVars[versionTokens[0].value];
const varData = findVariable(versionTokens[0].value, ctx);
if (varData) {
dep.groupName = varData.key;
dep.managerData = {
Expand Down Expand Up @@ -233,7 +234,7 @@ export function handlePlugin(ctx: Ctx): Ctx {
// = template string with multiple variables
dep.skipReason = 'unknown-version';
} else if (pluginVersion[0].type === 'symbol') {
const varData = ctx.globalVars[pluginVersion[0].value];
const varData = findVariable(pluginVersion[0].value, ctx);
if (varData) {
dep.groupName = varData.key;
dep.currentValue = varData.value;
Expand Down Expand Up @@ -276,7 +277,7 @@ export function handleCustomRegistryUrl(ctx: Ctx): Ctx {

if (ctx.tokenMap.name) {
const nameTokens = loadFromTokenMap(ctx, 'name');
const nameValue = interpolateString(nameTokens, localVariables);
const nameValue = interpolateString(nameTokens, ctx, localVariables);
if (nameValue) {
localVariables = {
...localVariables,
Expand All @@ -290,6 +291,7 @@ export function handleCustomRegistryUrl(ctx: Ctx): Ctx {

let registryUrl = interpolateString(
loadFromTokenMap(ctx, 'registryUrl'),
ctx,
localVariables
);
if (registryUrl) {
Expand All @@ -314,8 +316,8 @@ export function handleLibraryDep(ctx: Ctx): Ctx {
const groupIdTokens = loadFromTokenMap(ctx, 'groupId');
const artifactIdTokens = loadFromTokenMap(ctx, 'artifactId');

const groupId = interpolateString(groupIdTokens, ctx.globalVars);
const artifactId = interpolateString(artifactIdTokens, ctx.globalVars);
const groupId = interpolateString(groupIdTokens, ctx);
const artifactId = interpolateString(artifactIdTokens, ctx);
if (!groupId || !artifactId) {
return ctx;
}
Expand All @@ -331,10 +333,7 @@ export function handleLibraryDep(ctx: Ctx): Ctx {
};

if (ctx.tokenMap.version) {
const version = interpolateString(
loadFromTokenMap(ctx, 'version'),
ctx.globalVars
);
const version = interpolateString(loadFromTokenMap(ctx, 'version'), ctx);
if (version) {
handleLongFormDep(ctx);
}
Expand All @@ -344,18 +343,15 @@ export function handleLibraryDep(ctx: Ctx): Ctx {
}

export function handleApplyFrom(ctx: Ctx): Ctx {
let scriptFile = interpolateString(
loadFromTokenMap(ctx, 'scriptFile'),
ctx.globalVars
);
let scriptFile = interpolateString(loadFromTokenMap(ctx, 'scriptFile'), ctx);
if (!scriptFile) {
return ctx;
}

if (ctx.tokenMap.parentPath) {
const parentPath = interpolateString(
loadFromTokenMap(ctx, 'parentPath'),
ctx.globalVars
ctx
);
if (parentPath && scriptFile) {
scriptFile = upath.join(parentPath, scriptFile);
Expand Down Expand Up @@ -397,7 +393,7 @@ export function handleApplyFrom(ctx: Ctx): Ctx {
export function handleImplicitGradlePlugin(ctx: Ctx): Ctx {
const pluginName = loadFromTokenMap(ctx, 'pluginName')[0].value;
const versionTokens = loadFromTokenMap(ctx, 'version');
const versionValue = interpolateString(versionTokens, ctx.globalVars);
const versionValue = interpolateString(versionTokens, ctx);
if (!versionValue) {
return ctx;
}
Expand All @@ -420,7 +416,7 @@ export function handleImplicitGradlePlugin(ctx: Ctx): Ctx {
// = template string with multiple variables
dep.skipReason = 'unknown-version';
} else if (versionTokens[0].type === 'symbol') {
const varData = ctx.globalVars[versionTokens[0].value];
const varData = findVariable(versionTokens[0].value, ctx);
if (varData) {
dep.groupName = varData.key;
dep.currentValue = varData.value;
Expand Down