Skip to content

Commit

Permalink
feat(manager/gradle): add support for Kotlin import directives (#25486
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Churro committed Oct 28, 2023
1 parent 60d2b5f commit a57cdfd
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 1 deletion.
37 changes: 37 additions & 0 deletions lib/modules/manager/gradle/parser.spec.ts
Expand Up @@ -1053,5 +1053,42 @@ describe('modules/manager/gradle/parser', () => {
],
});
});

it('imported objects', () => {
const input = codeBlock`
object ModuleConfiguration {
object Build {
object Database {
const val h2Version = "2.0.206"
}
}
}
`;

const gradleKtsInput = codeBlock`
import ModuleConfiguration.Build.Database
dependencies {
runtimeOnly("com.h2database:h2:\${Database.h2Version}")
}
`;

const { vars } = parseKotlinSource(input);
const res = parseGradle(gradleKtsInput, vars);
expect(res).toMatchObject({
vars: {
'ModuleConfiguration.Build.Database.h2Version': {
key: 'ModuleConfiguration.Build.Database.h2Version',
value: '2.0.206',
},
},
deps: [
{
depName: 'com.h2database:h2',
currentValue: '2.0.206',
groupName: 'ModuleConfiguration.Build.Database.h2Version',
},
],
});
});
});
});
3 changes: 3 additions & 0 deletions lib/modules/manager/gradle/parser.ts
Expand Up @@ -3,6 +3,7 @@ import { newlineRegex, regEx } from '../../../util/regex';
import type { PackageDependency } from '../types';
import { qApplyFrom } from './parser/apply-from';
import { qAssignments } from './parser/assignments';
import { qKotlinImport } from './parser/common';
import { qDependencies, qLongFormDep } from './parser/dependencies';
import { setParseGradleFunc } from './parser/handlers';
import { qKotlinMultiObjectVarAssignment } from './parser/objects';
Expand All @@ -29,6 +30,7 @@ const ctx: Ctx = {
registryUrls: [],

varTokens: [],
tmpKotlinImportStore: [],
tmpNestingDepth: [],
tmpTokenStore: {},
tokenMap: {},
Expand All @@ -51,6 +53,7 @@ export function parseGradle(
type: 'root-tree',
maxDepth: 32,
search: q.alt<Ctx>(
qKotlinImport,
qAssignments,
qDependencies,
qPlugins,
Expand Down
6 changes: 6 additions & 0 deletions lib/modules/manager/gradle/parser/common.spec.ts
Expand Up @@ -30,6 +30,7 @@ describe('modules/manager/gradle/parser/common', () => {
registryUrls: [],

varTokens: [],
tmpKotlinImportStore: [],
tmpNestingDepth: [],
tmpTokenStore: {},
tokenMap: {},
Expand Down Expand Up @@ -139,6 +140,11 @@ describe('modules/manager/gradle/parser/common', () => {

ctx.tmpNestingDepth = [];
expect(findVariable('foo', ctx)).toStrictEqual(ctx.globalVars['foo']);

ctx.tmpKotlinImportStore = [[token, token]];
expect(findVariable('test.foo3', ctx)).toStrictEqual(
ctx.globalVars['test.test.foo3']
);
});

it('interpolateString', () => {
Expand Down
42 changes: 41 additions & 1 deletion lib/modules/manager/gradle/parser/common.ts
Expand Up @@ -112,6 +112,31 @@ export function coalesceVariable(ctx: Ctx): Ctx {
return ctx;
}

export function findVariableInKotlinImport(
name: string,
ctx: Ctx,
variables: PackageVariables
): VariableData | undefined {
if (ctx.tmpKotlinImportStore.length && name.includes('.')) {
for (const tokens of ctx.tmpKotlinImportStore) {
const lastToken = tokens[tokens.length - 1];
if (lastToken && name.startsWith(`${lastToken.value}.`)) {
const prefix = tokens
.slice(0, -1)
.map((token) => token.value)
.join('.');
const identifier = `${prefix}.${name}`;

if (variables[identifier]) {
return variables[identifier];
}
}
}
}

return undefined;
}

export function findVariable(
name: string,
ctx: Ctx,
Expand All @@ -129,7 +154,11 @@ export function findVariable(
}
}

return variables[name];
if (variables[name]) {
return variables[name];
}

return findVariableInKotlinImport(name, ctx, variables);
}

export function interpolateString(
Expand Down Expand Up @@ -271,3 +300,14 @@ export const qValueMatcher = qConcatExpr(
qPropertyAccessIdentifier,
qVariableAccessIdentifier
);

// import foo.bar
// runtimeOnly("some:foo:${bar.bazVersion}")
export const qKotlinImport = q
.sym<Ctx>('import')
.join(qVariableAssignmentIdentifier)
.handler((ctx) => {
ctx.tmpKotlinImportStore.push(ctx.varTokens);
return ctx;
})
.handler(cleanupTempVars);
1 change: 1 addition & 0 deletions lib/modules/manager/gradle/types.ts
Expand Up @@ -82,6 +82,7 @@ export interface Ctx {
registryUrls: PackageRegistry[];

varTokens: lexer.Token[];
tmpKotlinImportStore: lexer.Token[][];
tmpNestingDepth: lexer.Token[];
tmpTokenStore: Record<string, lexer.Token[]>;
tokenMap: Record<string, lexer.Token[]>;
Expand Down

0 comments on commit a57cdfd

Please sign in to comment.