import { regEx } from '../../../util/regex' ; import type { BuildDependency , GradleDependency , UpdateFunction , } from './types' ; /**
 * Functions adapted/ported from https://github.com/patrikerdes/gradle-use-latest-versions-plugin
 * gradle-use-latest-versions-plugin is licensed under MIT and Copyright (c) 2018 Patrik Erdes
 */ let variables = { } ; const groovyQuotes = `(?:["'](?:""|'')?)` ; const groovyVersionVariable = `(?:${ groovyQuotes }\\$)?{?([^\\s"'{}$)]+)}?${ groovyQuotes }?` ; const kotlinVersionVariable = `(?:"\\$)?{?([^\\s"{}$]+?)}?"?` ; function moduleStringVersionFormatMatch ( dependency ) { return regEx ( `(${ groovyQuotes }${ dependency . group }:${ dependency . name }:)[^$].*?(([:@].*?)?${ groovyQuotes })` ) ; } function groovyPluginStringVersionFormatMatch ( dependency ) { return regEx ( `(id\\s+${ groovyQuotes }${ dependency . group }${ groovyQuotes }\\s+version\\s+${ groovyQuotes })[^"$].*?(${ groovyQuotes })` ) ; } function kotlinPluginStringVersionFormatMatch ( dependency ) { return regEx ( `(id\\("${ dependency . group }"\\)\\s+version\\s+")[^$].*?(")` , undefined , false ) ; } function dependencyStringVersionFormatMatch ( dependency ) { return regEx ( `(dependency\\s+['"]${ dependency . group }:${ dependency . name }:)[^'"]+(['"])` , undefined , false ) ; } function allMapFormatOrders ( group , name , version , prefix , postfix ) { const comma = '\\s*,\\s*' ; return [ `${ group }${ comma }${ name }${ comma }${ version }` , `${ group }${ comma }${ version }${ comma }${ name }` , `${ name }${ comma }${ group }${ comma }${ version }` , `${ version }${ comma }${ group }${ comma }${ name }` , `${ name }${ comma }${ version }${ comma }${ group }` , `${ version }${ comma }${ name }${ comma }${ group }` , ] . map ( ( regex ) => regEx ( `${ prefix }${ regex }${ postfix }` , undefined , false ) ) ; } function moduleMapVersionFormatMatch ( dependency ) { const group = `group\\s*:\\s*${ groovyQuotes }${ dependency . group }${ groovyQuotes }` ; const name = `name\\s*:\\s*${ groovyQuotes }${ dependency . name }${ groovyQuotes }` ; const version = `version\\s*:\\s*${ groovyQuotes })[^{}$"']+?(${ groovyQuotes }` ; return allMapFormatOrders ( group , name , version , '(' , ')' ) ; } function moduleKotlinNamedArgumentVersionFormatMatch ( dependency ) { const group = `group\\s*=\\s*"${ dependency . group }"` ; const name = `name\\s*=\\s*"${ dependency . name }"` ; const version = `version\\s*=\\s*")[^{}$]*?("` ; return allMapFormatOrders ( group , name , version , '(' , ')' ) ; } function moduleMapVariableVersionFormatMatch ( dependency ) { const group = `group\\s*:\\s*${ groovyQuotes }${ dependency . group }${ groovyQuotes }` ; const name = `name\\s*:\\s*${ groovyQuotes }${ dependency . name }${ groovyQuotes }` ; const version = `version\\s*:\\s*${ groovyVersionVariable }` ; return allMapFormatOrders ( group , name , version , '' , '' ) ; } function moduleKotlinNamedArgumentVariableVersionFormatMatch ( dependency ) { const group = `group\\s*=\\s*"${ dependency . group }"` ; const name = `name\\s*=\\s*"${ dependency . name }"` ; const version = `version\\s*=\\s*${ kotlinVersionVariable }` ; return allMapFormatOrders ( group , name , version , '' , '[\\s),]' ) ; } function moduleStringVariableInterpolationVersionFormatMatch ( dependency ) { return regEx ( `${ groovyQuotes }${ dependency . group }:${ dependency . name }:\\$([^{].*?)${ groovyQuotes }` ) ; } function moduleStringVariableExpressionVersionFormatMatch ( dependency ) { return regEx ( `${ groovyQuotes }${ dependency . group }:${ dependency . name }:\\$` + `{([^{].*?)}${ groovyQuotes }` ) ; } function groovyPluginVariableVersionFormatMatch ( dependency ) { return regEx ( `id\\s+${ groovyQuotes }${ dependency . group }${ groovyQuotes }\\s+version\\s+${ groovyVersionVariable }(?:\\s|;|})` ) ; } function kotlinPluginVariableVersionFormatMatch ( dependency ) { return regEx ( `id\\("${ dependency . group }"\\)\\s+version\\s+${ kotlinVersionVariable }(?:\\s|;|})` ) ; } function kotlinImplementationVariableVersionFormatMatch ( dependency ) { return regEx ( `(?:implementation|testImplementation)\\s*\\(\\s*['"]${ dependency . group }['"]\\s*,\\s*['"]${ dependency . name }['"]\\s*,\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\)\\s*(?:\\s|;|})` ) ; } function kotlinPluginVariableDotVersionFormatMatch ( dependency ) { return regEx ( `id\\s*\\(\\s*"${ dependency . group }"\\s*\\)\\s*\\.\\s*version\\s*\\(\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\)\\s*(?:\\s|;|})` ) ; } function dependencyStringVariableExpressionFormatMatch ( dependency ) { return regEx ( `\\s*dependency\\s+['"]${ dependency . group }:${ dependency . name }:` + '${([^}]*)}' + `['"](?:\\s|;|})` ) ; } function dependencyStringLiteralExpressionFormatMatch ( dependency ) { return regEx ( `\\s*dependency\\s+['"]${ dependency . group }:${ dependency . name }:([^'"{}$]+)['"](?:\\s|;|})` ) ; } function variableDefinitionFormatMatch ( variable ) { return regEx ( `(${ variable }\\s*=\\s*?["'])(.*)(["'])` ) ; } function variableMapDefinitionFormatMatch ( variable , version ) { return regEx ( `(${ variable }\\s*:\\s*?["'])(${ version })(["'])` , undefined , false ) ; } export function collectVersionVariables ( dependencies , buildGradleContent ) { for ( const dep of dependencies ) { const dependency = { ... dep , group : dep . depGroup , } ; const regexes = [ moduleStringVariableExpressionVersionFormatMatch ( dependency ) , moduleStringVariableInterpolationVersionFormatMatch ( dependency ) , groovyPluginVariableVersionFormatMatch ( dependency ) , kotlinPluginVariableVersionFormatMatch ( dependency ) , dependencyStringVariableExpressionFormatMatch ( dependency ) , ... moduleMapVariableVersionFormatMatch ( dependency ) , ... moduleKotlinNamedArgumentVariableVersionFormatMatch ( dependency ) , kotlinImplementationVariableVersionFormatMatch ( dependency ) , kotlinPluginVariableDotVersionFormatMatch ( dependency ) , ] ; const depName = `${ dependency . group }:${ dependency . name }` ; for ( const regex of regexes ) { const match = regex . exec ( buildGradleContent ) ; if ( match ) { variables [ depName ] = match [ 1 ] ; } } if ( ! dep . currentValue ) { const dependencyLiteralRegex = dependencyStringLiteralExpressionFormatMatch ( dependency ) ; const currentValue = dependencyLiteralRegex . exec ( buildGradleContent ) ?. [ 1 ] ; if ( currentValue ) { dep . currentValue = currentValue ; } } } } export function init ( ) { variables = { } ; } function updateVersionLiterals ( dependency , buildGradleContent , newValue ) { const regexes = [ moduleStringVersionFormatMatch ( dependency ) , groovyPluginStringVersionFormatMatch ( dependency ) , kotlinPluginStringVersionFormatMatch ( dependency ) , dependencyStringVersionFormatMatch ( dependency ) , ... moduleMapVersionFormatMatch ( dependency ) , ... moduleKotlinNamedArgumentVersionFormatMatch ( dependency ) , ] ; let result = buildGradleContent ; for ( const regex of regexes ) { const match = regex . exec ( result ) ; if ( match ) { result = result . replace ( match [ 0 ] , `${ match [ 1 ] }${ newValue }${ match [ 2 ] }` ) ; } } return result === buildGradleContent ? null : result ; } function updateLocalVariables ( dependency , buildGradleContent , newValue ) { const regexes = [ ... moduleMapVariableVersionFormatMatch ( dependency ) , moduleStringVariableInterpolationVersionFormatMatch ( dependency ) , moduleStringVariableExpressionVersionFormatMatch ( dependency ) , groovyPluginVariableVersionFormatMatch ( dependency ) , kotlinPluginVariableVersionFormatMatch ( dependency ) , kotlinImplementationVariableVersionFormatMatch ( dependency ) , ... moduleKotlinNamedArgumentVariableVersionFormatMatch ( dependency ) , ] ; for ( const regex of regexes ) { const match = regex . exec ( buildGradleContent ) ; if ( match ) { const variableDefinitionRegex = variableDefinitionFormatMatch ( match [ 1 ] ) ; const variableDefinitionMatch = variableDefinitionRegex . exec ( buildGradleContent ) ; if ( variableDefinitionMatch ) { return buildGradleContent . replace ( variableDefinitionMatch [ 0 ] , `${ variableDefinitionMatch [ 1 ] }${ newValue }${ variableDefinitionMatch [ 3 ] }` ) ; } } } return null ; } function updateGlobalVariables ( dependency , buildGradleContent , newValue ) { const variable = variables [ `${ dependency . group }:${ dependency . name }` ] ; if ( variable ) { const regex = variableDefinitionFormatMatch ( variable ) ; const match = regex . exec ( buildGradleContent ) ; if ( match ) { return buildGradleContent . replace ( match [ 0 ] , `${ match [ 1 ] }${ newValue }${ match [ 3 ] }` ) ; } } return null ; } function updateGlobalMapVariables ( dependency , buildGradleContent , newValue ) { let variable = variables [ `${ dependency . group }:${ dependency . name }` ] ; if ( variable && dependency . version ) { while ( variable && variable . split ( '.' ) . length > 0 ) { const regex = variableMapDefinitionFormatMatch ( variable , dependency . version ) ; const match = regex . exec ( buildGradleContent ) ; if ( match ) { return buildGradleContent . replace ( match [ 0 ] , `${ match [ 1 ] }${ newValue }${ match [ 3 ] }` ) ; } variable = variable . split ( '.' ) . splice ( 1 ) . join ( '.' ) ; } } return null ; } function updateKotlinVariablesByExtra ( dependency , buildGradleContent , newValue ) { const variable = variables [ `${ dependency . group }:${ dependency . name }` ] ; if ( variable ) { const regex = regEx ( `(val ${ variable } by extra(?: {|\\()\\s*")(.*)("\\s*[})])` ) ; const match = regex . exec ( buildGradleContent ) ; if ( match ) { return buildGradleContent . replace ( match [ 0 ] , `${ match [ 1 ] }${ newValue }${ match [ 3 ] }` ) ; } } return null ; } function updatePropertyFileGlobalVariables ( dependency , buildGradleContent , newValue ) { const variable = variables [ `${ dependency . group }:${ dependency . name }` ] ; if ( variable ) { const regex = regEx ( `(${ variable }\\s*=\\s*)(.*)` , undefined , false ) ; const match = regex . exec ( buildGradleContent ) ; if ( match ) { return buildGradleContent . replace ( match [ 0 ] , `${ match [ 1 ] }${ newValue }` ) ; } } return null ; } export function updateGradleVersion ( buildGradleContent , dependency , newValue ) { if ( dependency ) { const updateFunctions = [ updateVersionLiterals , updateLocalVariables , updateGlobalVariables , updateGlobalMapVariables , updatePropertyFileGlobalVariables , updateKotlinVariablesByExtra , ] ; for ( const updateFunction of updateFunctions ) { const gradleContentUpdated = updateFunction ( dependency , buildGradleContent , newValue ) ; if ( gradleContentUpdated ) { return gradleContentUpdated ; } } } return buildGradleContent ; }