diff --git a/lib/modules/manager/gradle/parser.ts b/lib/modules/manager/gradle/parser.ts index 02a788145d25c7bbcd507b942687a46dcee0bd13..edc0040911874140f10ea2900d828fb1938d06cc 100644 --- a/lib/modules/manager/gradle/parser.ts +++ b/lib/modules/manager/gradle/parser.ts @@ -56,6 +56,7 @@ export function parseGradle( registryUrls: [], varTokens: [], + tmpNestingDepth: [], tmpTokenStore: {}, tokenMap: {}, }); diff --git a/lib/modules/manager/gradle/parser/assignments.ts b/lib/modules/manager/gradle/parser/assignments.ts index e8af871ffa3674d5c19017bbcf82f1184320c1cb..9b5ccbd49ba4615373e32957ee11f1a068b3a03f 100644 --- a/lib/modules/manager/gradle/parser/assignments.ts +++ b/lib/modules/manager/gradle/parser/assignments.ts @@ -4,9 +4,12 @@ import type { Ctx } from '../types'; import { cleanupTempVars, coalesceVariable, + increaseNestingDepth, + prependNestingDepth, qStringValue, qTemplateString, qVariableAssignmentIdentifier, + reduceNestingDepth, storeInTokenMap, storeVarToken, } from './common'; @@ -65,40 +68,27 @@ const qKotlinSingleExtraVarAssignment = q // foo: "1.2.3" const qGroovySingleMapOfVarAssignment = q .sym(storeVarToken) - .handler((ctx) => { - ctx.tmpTokenStore.backupVarTokens = ctx.varTokens; - return ctx; - }) + .handler(prependNestingDepth) .handler(coalesceVariable) .handler((ctx) => storeInTokenMap(ctx, 'keyToken')) .op(':') .join(qTemplateString) .handler((ctx) => storeInTokenMap(ctx, 'valToken')) - .handler(handleAssignment) - .handler((ctx) => { - ctx.varTokens = ctx.tmpTokenStore.backupVarTokens!; - ctx.varTokens.pop(); - return ctx; - }); + .handler(handleAssignment); const qGroovyMapOfExpr = ( search: q.QueryBuilder<Ctx, parser.Node> ): q.QueryBuilder<Ctx, parser.Node> => q.alt( - q - .sym(storeVarToken) - .op(':') - .tree({ - type: 'wrapped-tree', - maxDepth: 1, - startsWith: '[', - endsWith: ']', - search, - postHandler: (ctx: Ctx) => { - ctx.varTokens.pop(); - return ctx; - }, - }), + q.sym(storeVarToken).op(':').tree({ + type: 'wrapped-tree', + maxDepth: 1, + startsWith: '[', + endsWith: ']', + preHandler: increaseNestingDepth, + search, + postHandler: reduceNestingDepth, + }), qGroovySingleMapOfVarAssignment ); @@ -110,46 +100,35 @@ const qGroovyMultiVarAssignment = qVariableAssignmentIdentifier maxDepth: 1, startsWith: '[', endsWith: ']', + preHandler: increaseNestingDepth, search: qGroovyMapOfExpr(qGroovyMapOfExpr(qGroovySingleMapOfVarAssignment)), + postHandler: reduceNestingDepth, }) .handler(cleanupTempVars); // "foo1" to "bar1" const qKotlinSingleMapOfVarAssignment = qStringValue .sym('to') - .handler((ctx) => { - ctx.tmpTokenStore.backupVarTokens = ctx.varTokens; - return ctx; - }) + .handler(prependNestingDepth) .handler(coalesceVariable) .handler((ctx) => storeInTokenMap(ctx, 'keyToken')) .join(qTemplateString) .handler((ctx) => storeInTokenMap(ctx, 'valToken')) - .handler(handleAssignment) - .handler((ctx) => { - ctx.varTokens = ctx.tmpTokenStore.backupVarTokens!; - ctx.varTokens.pop(); - return ctx; - }); + .handler(handleAssignment); const qKotlinMapOfExpr = ( search: q.QueryBuilder<Ctx, parser.Node> ): q.QueryBuilder<Ctx, parser.Node> => q.alt( - qStringValue - .sym('to') - .sym('mapOf') - .tree({ - type: 'wrapped-tree', - maxDepth: 1, - startsWith: '(', - endsWith: ')', - search, - postHandler: (ctx: Ctx) => { - ctx.varTokens.pop(); - return ctx; - }, - }), + qStringValue.sym('to').sym('mapOf').tree({ + type: 'wrapped-tree', + maxDepth: 1, + startsWith: '(', + endsWith: ')', + preHandler: increaseNestingDepth, + search, + postHandler: reduceNestingDepth, + }), qKotlinSingleMapOfVarAssignment ); @@ -162,7 +141,9 @@ const qKotlinMultiMapOfVarAssignment = qVariableAssignmentIdentifier maxDepth: 1, startsWith: '(', endsWith: ')', + preHandler: increaseNestingDepth, search: qKotlinMapOfExpr(qKotlinMapOfExpr(qKotlinSingleMapOfVarAssignment)), + postHandler: reduceNestingDepth, }) .handler(cleanupTempVars); diff --git a/lib/modules/manager/gradle/parser/common.spec.ts b/lib/modules/manager/gradle/parser/common.spec.ts index 7b8779b0a17f791a97ba0f390a321870dac56601..c2742363c049a73da6f16d175cccb645750cbbf3 100644 --- a/lib/modules/manager/gradle/parser/common.spec.ts +++ b/lib/modules/manager/gradle/parser/common.spec.ts @@ -4,8 +4,11 @@ import type { Ctx, PackageVariables } from '../types'; import { cleanupTempVars, coalesceVariable, + increaseNestingDepth, interpolateString, loadFromTokenMap, + prependNestingDepth, + reduceNestingDepth, storeInTokenMap, storeVarToken, stripReservedPrefixFromKeyTokens, @@ -13,7 +16,7 @@ import { describe('modules/manager/gradle/parser/common', () => { let ctx: Ctx; - const token = partial<lexer.Token>({}); + const token = partial<lexer.Token>({ value: 'test' }); beforeEach(() => { ctx = { @@ -26,6 +29,7 @@ describe('modules/manager/gradle/parser/common', () => { registryUrls: [], varTokens: [], + tmpNestingDepth: [], tmpTokenStore: {}, tokenMap: {}, }; @@ -36,6 +40,33 @@ describe('modules/manager/gradle/parser/common', () => { expect(ctx.varTokens).toStrictEqual([token]); }); + it('increaseNestingDepth', () => { + ctx.tmpNestingDepth = ctx.varTokens = [token]; + increaseNestingDepth(ctx); + expect(ctx).toMatchObject({ + tmpNestingDepth: [token, token], + varTokens: [], + }); + }); + + it('reduceNestingDepth', () => { + ctx.tmpNestingDepth = [token, token]; + reduceNestingDepth(ctx); + expect(ctx.tmpNestingDepth).toHaveLength(1); + }); + + it('prependNestingDepth', () => { + ctx.tmpNestingDepth = ctx.varTokens = [token]; + prependNestingDepth(ctx); + expect(ctx.varTokens).toStrictEqual([token, token]); + + coalesceVariable(ctx); + expect(ctx).toMatchObject({ + tmpNestingDepth: [{ value: 'test' }], + varTokens: [{ value: 'test.test' }], + }); + }); + it('storeInTokenMap', () => { ctx.varTokens = [token]; storeInTokenMap(ctx, 'foo'); diff --git a/lib/modules/manager/gradle/parser/common.ts b/lib/modules/manager/gradle/parser/common.ts index 6f73dae18b41785bc83cafe83a395f7d428d18f0..69fddc91470dd81d370e81a4efe4cbc7424038ab 100644 --- a/lib/modules/manager/gradle/parser/common.ts +++ b/lib/modules/manager/gradle/parser/common.ts @@ -1,4 +1,5 @@ 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'; @@ -39,6 +40,22 @@ export function storeVarToken(ctx: Ctx, node: lexer.Token): Ctx { return ctx; } +export function increaseNestingDepth(ctx: Ctx): Ctx { + ctx.tmpNestingDepth.push(...ctx.varTokens); + ctx.varTokens = []; + return ctx; +} + +export function reduceNestingDepth(ctx: Ctx): Ctx { + ctx.tmpNestingDepth.pop(); + return ctx; +} + +export function prependNestingDepth(ctx: Ctx): Ctx { + ctx.varTokens = [...clone(ctx.tmpNestingDepth), ...ctx.varTokens]; + return ctx; +} + export function storeInTokenMap(ctx: Ctx, tokenMapKey: string): Ctx { ctx.tokenMap[tokenMapKey] = ctx.varTokens; ctx.varTokens = []; diff --git a/lib/modules/manager/gradle/types.ts b/lib/modules/manager/gradle/types.ts index a4646dbef8ab8619c1c57b93fee1ee330493ceff..7222c36345aa7111d232dcd6d34665ff9b9bb92f 100644 --- a/lib/modules/manager/gradle/types.ts +++ b/lib/modules/manager/gradle/types.ts @@ -82,6 +82,7 @@ export interface Ctx { registryUrls: PackageRegistry[]; varTokens: lexer.Token[]; + tmpNestingDepth: lexer.Token[]; tmpTokenStore: Record<string, lexer.Token[]>; tokenMap: Record<string, lexer.Token[]>; }