@@ -544,9 +544,15 @@ class StrategyImpl extends AstNodeImpl, TStrategyNode {
544544
545545 override YamlMapping getNode ( ) { result = n }
546546
547- /** Gets a specific matric expression (YamlMapping) by name. */
548- ExpressionImpl getMatrixVarExpr ( string name ) {
549- n .lookup ( "matrix" ) .( YamlMapping ) .lookup ( name ) = result .getNode ( )
547+ YamlMapping getMatrix ( ) { result = n .lookup ( "matrix" ) }
548+
549+ /** Gets a specific matrix expression (YamlMapping) by name. */
550+ ExpressionImpl getMatrixVarExpr ( string accessPath ) {
551+ exists ( MatrixAccessPathImpl p , ScalarValueImpl v |
552+ p .toString ( ) = accessPath and
553+ resolveMatrixAccessPath ( n .lookup ( "matrix" ) , p ) .getNode ( _) = v .getNode ( ) and
554+ result .getParentNode ( ) = v
555+ )
550556 }
551557
552558 /** Gets a specific matric expression (YamlMapping) by name. */
@@ -777,14 +783,27 @@ class JobImpl extends AstNodeImpl, TJobNode {
777783
778784 /** Gets the runs-on field of the job. */
779785 string getARunsOnLabel ( ) {
780- exists ( string lbl , YamlNode r |
786+ exists ( ScalarValueImpl lbl |
781787 (
782- r = runson .getNode ( lbl ) and
783- not lbl = [ "group" , "labels" ]
788+ lbl . getNode ( ) = runson .getNode ( _ ) and
789+ not lbl . getNode ( ) = runson . getNode ( "group" )
784790 or
785- r = runson .getNode ( "labels" ) .( YamlMappingLikeNode ) .getNode ( lbl )
791+ lbl . getNode ( ) = runson .getNode ( "labels" ) .( YamlMappingLikeNode ) .getNode ( _ )
786792 ) and
787- result = lbl .trim ( ) .regexpReplaceAll ( "^('|\")" , "" ) .regexpReplaceAll ( "('|\")$" , "" ) .trim ( )
793+ (
794+ not exists ( MatrixExpressionImpl e | e .getParentNode ( ) = lbl ) and
795+ result =
796+ lbl .getValue ( )
797+ .trim ( )
798+ .regexpReplaceAll ( "^('|\")" , "" )
799+ .regexpReplaceAll ( "('|\")$" , "" )
800+ .trim ( )
801+ or
802+ exists ( MatrixExpressionImpl e |
803+ e .getParentNode ( ) = lbl and
804+ result = e .getLiteralValues ( )
805+ )
806+ )
788807 )
789808 }
790809}
@@ -1050,7 +1069,7 @@ private string jobsCtxRegex() {
10501069
10511070private string envCtxRegex ( ) { result = Utils:: wrapRegexp ( "env\\.([A-Za-z0-9_-]+)" ) }
10521071
1053- private string matrixCtxRegex ( ) { result = Utils:: wrapRegexp ( "matrix\\.([A-Za-z0-9_-] +)" ) }
1072+ private string matrixCtxRegex ( ) { result = Utils:: wrapRegexp ( "matrix\\.(. +)" ) }
10541073
10551074private string inputsCtxRegex ( ) {
10561075 result =
@@ -1224,24 +1243,65 @@ class EnvExpressionImpl extends SimpleReferenceExpressionImpl {
12241243 * e.g. `${{ matrix.foo }}`
12251244 */
12261245class MatrixExpressionImpl extends SimpleReferenceExpressionImpl {
1227- string fieldName ;
1246+ string fieldAccess ;
12281247
12291248 MatrixExpressionImpl ( ) {
12301249 Utils:: normalizeExpr ( expression ) .regexpMatch ( matrixCtxRegex ( ) ) and
1231- fieldName = Utils:: normalizeExpr ( expression ) .regexpCapture ( matrixCtxRegex ( ) , 1 )
1250+ fieldAccess = Utils:: normalizeExpr ( expression ) .regexpCapture ( matrixCtxRegex ( ) , 1 )
12321251 }
12331252
1234- override string getFieldName ( ) { result = fieldName }
1253+ override string getFieldName ( ) { result = fieldAccess }
12351254
12361255 override AstNodeImpl getTarget ( ) {
1237- exists ( WorkflowImpl w |
1238- w .getStrategy ( ) .getMatrixVarExpr ( fieldName ) = result and
1239- w .getAChildNode * ( ) = this
1240- )
1241- or
1242- exists ( JobImpl j |
1243- j .getStrategy ( ) .getMatrixVarExpr ( fieldName ) = result and
1244- j .getAChildNode * ( ) = this
1256+ result = this .getEnclosingWorkflow ( ) .getStrategy ( ) .getMatrixVarExpr ( fieldAccess ) or
1257+ result = this .getEnclosingJob ( ) .getStrategy ( ) .getMatrixVarExpr ( fieldAccess )
1258+ }
1259+
1260+ string getLiteralValues ( ) {
1261+ exists ( StrategyImpl s , MatrixAccessPathImpl p , ScalarValueImpl v |
1262+ ( s = this .getEnclosingJob ( ) .getStrategy ( ) or s = this .getEnclosingWorkflow ( ) .getStrategy ( ) ) and
1263+ p .toString ( ) = fieldAccess and
1264+ resolveMatrixAccessPath ( s .getMatrix ( ) , p ) .getNode ( _) = v .getNode ( ) and
1265+ // Exclude values containing matrix expressions to avoid recursion
1266+ not exists ( MatrixExpressionImpl e | e .getParentNode ( ) = v ) and
1267+ result = v .getValue ( )
12451268 )
12461269 }
12471270}
1271+
1272+ bindingset [ accessPath]
1273+ string explodeAccessPath ( string accessPath ) {
1274+ result = accessPath or
1275+ result = accessPath .suffix ( accessPath .indexOf ( "." ) + 1 ) or
1276+ result = accessPath .prefix ( accessPath .indexOf ( "." ) )
1277+ }
1278+
1279+ private newtype TAccessPath =
1280+ TMatrixAccessPathNode ( string accessPath ) {
1281+ exists ( MatrixExpressionImpl e | accessPath = explodeAccessPath ( e .getFieldName ( ) ) )
1282+ }
1283+
1284+ class MatrixAccessPathImpl extends TMatrixAccessPathNode {
1285+ string accessPath ;
1286+
1287+ MatrixAccessPathImpl ( ) { this = TMatrixAccessPathNode ( accessPath ) }
1288+
1289+ string toString ( ) { result = accessPath }
1290+ }
1291+
1292+ private YamlMappingLikeNode resolveMatrixAccessPath (
1293+ YamlMappingLikeNode root , MatrixAccessPathImpl accessPath
1294+ ) {
1295+ // access path contains no dots. eg: "os"
1296+ result = root .getNode ( accessPath .toString ( ) )
1297+ or
1298+ // access path contains dots. eg: "plaform.os"
1299+ exists ( MatrixAccessPathImpl first , MatrixAccessPathImpl rest , YamlMappingLikeNode newRoot |
1300+ first .toString ( ) = accessPath .toString ( ) .splitAt ( "." , 0 ) and
1301+ rest .toString ( ) = accessPath .toString ( ) .suffix ( first .toString ( ) .length ( ) + 1 ) and
1302+ newRoot = root .getNode ( first .toString ( ) ) and
1303+ if newRoot instanceof YamlSequence
1304+ then result = resolveMatrixAccessPath ( newRoot .( YamlSequence ) .getElementNode ( _) , rest )
1305+ else result = resolveMatrixAccessPath ( newRoot , rest )
1306+ )
1307+ }
0 commit comments