@@ -544,9 +544,15 @@ class StrategyImpl extends AstNodeImpl, TStrategyNode {
544
544
545
545
override YamlMapping getNode ( ) { result = n }
546
546
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
+ )
550
556
}
551
557
552
558
/** Gets a specific matric expression (YamlMapping) by name. */
@@ -777,14 +783,27 @@ class JobImpl extends AstNodeImpl, TJobNode {
777
783
778
784
/** Gets the runs-on field of the job. */
779
785
string getARunsOnLabel ( ) {
780
- exists ( string lbl , YamlNode r |
786
+ exists ( ScalarValueImpl lbl |
781
787
(
782
- r = runson .getNode ( lbl ) and
783
- not lbl = [ "group" , "labels" ]
788
+ lbl . getNode ( ) = runson .getNode ( _ ) and
789
+ not lbl . getNode ( ) = runson . getNode ( "group" )
784
790
or
785
- r = runson .getNode ( "labels" ) .( YamlMappingLikeNode ) .getNode ( lbl )
791
+ lbl . getNode ( ) = runson .getNode ( "labels" ) .( YamlMappingLikeNode ) .getNode ( _ )
786
792
) 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
+ )
788
807
)
789
808
}
790
809
}
@@ -1050,7 +1069,7 @@ private string jobsCtxRegex() {
1050
1069
1051
1070
private string envCtxRegex ( ) { result = Utils:: wrapRegexp ( "env\\.([A-Za-z0-9_-]+)" ) }
1052
1071
1053
- private string matrixCtxRegex ( ) { result = Utils:: wrapRegexp ( "matrix\\.([A-Za-z0-9_-] +)" ) }
1072
+ private string matrixCtxRegex ( ) { result = Utils:: wrapRegexp ( "matrix\\.(. +)" ) }
1054
1073
1055
1074
private string inputsCtxRegex ( ) {
1056
1075
result =
@@ -1224,24 +1243,65 @@ class EnvExpressionImpl extends SimpleReferenceExpressionImpl {
1224
1243
* e.g. `${{ matrix.foo }}`
1225
1244
*/
1226
1245
class MatrixExpressionImpl extends SimpleReferenceExpressionImpl {
1227
- string fieldName ;
1246
+ string fieldAccess ;
1228
1247
1229
1248
MatrixExpressionImpl ( ) {
1230
1249
Utils:: normalizeExpr ( expression ) .regexpMatch ( matrixCtxRegex ( ) ) and
1231
- fieldName = Utils:: normalizeExpr ( expression ) .regexpCapture ( matrixCtxRegex ( ) , 1 )
1250
+ fieldAccess = Utils:: normalizeExpr ( expression ) .regexpCapture ( matrixCtxRegex ( ) , 1 )
1232
1251
}
1233
1252
1234
- override string getFieldName ( ) { result = fieldName }
1253
+ override string getFieldName ( ) { result = fieldAccess }
1235
1254
1236
1255
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 ( )
1245
1268
)
1246
1269
}
1247
1270
}
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