29
29
import net .starlark .java .syntax .CallExpression ;
30
30
import net .starlark .java .syntax .Comprehension ;
31
31
import net .starlark .java .syntax .ConditionalExpression ;
32
+ import net .starlark .java .syntax .CoverageRecorder ;
32
33
import net .starlark .java .syntax .DefStatement ;
33
34
import net .starlark .java .syntax .DictExpression ;
34
35
import net .starlark .java .syntax .DotExpression ;
45
46
import net .starlark .java .syntax .ListExpression ;
46
47
import net .starlark .java .syntax .LoadStatement ;
47
48
import net .starlark .java .syntax .Location ;
49
+ import net .starlark .java .syntax .Parameter ;
48
50
import net .starlark .java .syntax .Resolver ;
49
51
import net .starlark .java .syntax .ReturnStatement ;
50
52
import net .starlark .java .syntax .SliceExpression ;
@@ -131,6 +133,7 @@ private static TokenKind execFor(StarlarkThread.Frame fr, ForStatement node)
131
133
continue ;
132
134
case BREAK :
133
135
// Finish loop, execute next statement after loop.
136
+ CoverageRecorder .getInstance ().recordVirtualJump (node );
134
137
return TokenKind .PASS ;
135
138
case RETURN :
136
139
// Finish loop, return from function.
@@ -145,6 +148,7 @@ private static TokenKind execFor(StarlarkThread.Frame fr, ForStatement node)
145
148
} finally {
146
149
EvalUtils .removeIterator (seq );
147
150
}
151
+ CoverageRecorder .getInstance ().recordVirtualJump (node );
148
152
return TokenKind .PASS ;
149
153
}
150
154
@@ -159,7 +163,9 @@ private static StarlarkFunction newFunction(StarlarkThread.Frame fr, Resolver.Fu
159
163
int nparams =
160
164
rfn .getParameters ().size () - (rfn .hasKwargs () ? 1 : 0 ) - (rfn .hasVarargs () ? 1 : 0 );
161
165
for (int i = 0 ; i < nparams ; i ++) {
162
- Expression expr = rfn .getParameters ().get (i ).getDefaultValue ();
166
+ Parameter parameter = rfn .getParameters ().get (i );
167
+ CoverageRecorder .getInstance ().recordCoverage (parameter .getIdentifier ());
168
+ Expression expr = parameter .getDefaultValue ();
163
169
if (expr == null && defaults == null ) {
164
170
continue ; // skip prefix of required parameters
165
171
}
@@ -169,6 +175,10 @@ private static StarlarkFunction newFunction(StarlarkThread.Frame fr, Resolver.Fu
169
175
defaults [i - (nparams - defaults .length )] =
170
176
expr == null ? StarlarkFunction .MANDATORY : eval (fr , expr );
171
177
}
178
+ // Visit kwargs and varargs for coverage.
179
+ for (int i = nparams ; i < rfn .getParameters ().size (); i ++) {
180
+ CoverageRecorder .getInstance ().recordCoverage (rfn .getParameters ().get (i ).getIdentifier ());
181
+ }
172
182
if (defaults == null ) {
173
183
defaults = EMPTY ;
174
184
}
@@ -206,6 +216,7 @@ private static TokenKind execIf(StarlarkThread.Frame fr, IfStatement node)
206
216
} else if (node .getElseBlock () != null ) {
207
217
return execStatements (fr , node .getElseBlock (), /*indented=*/ true );
208
218
}
219
+ CoverageRecorder .getInstance ().recordVirtualJump (node );
209
220
return TokenKind .PASS ;
210
221
}
211
222
@@ -262,6 +273,7 @@ private static TokenKind exec(StarlarkThread.Frame fr, Statement st)
262
273
if (++fr .thread .steps >= fr .thread .stepLimit ) {
263
274
throw new EvalException ("Starlark computation cancelled: too many steps" );
264
275
}
276
+ CoverageRecorder .getInstance ().recordCoverage (st );
265
277
266
278
switch (st .kind ()) {
267
279
case ASSIGNMENT :
@@ -330,6 +342,7 @@ private static void assign(StarlarkThread.Frame fr, Expression lhs, Object value
330
342
331
343
private static void assignIdentifier (StarlarkThread .Frame fr , Identifier id , Object value )
332
344
throws EvalException {
345
+ CoverageRecorder .getInstance ().recordCoverage (id );
333
346
Resolver .Binding bind = id .getBinding ();
334
347
switch (bind .getScope ()) {
335
348
case LOCAL :
@@ -477,6 +490,7 @@ private static Object eval(StarlarkThread.Frame fr, Expression expr)
477
490
if (++fr .thread .steps >= fr .thread .stepLimit ) {
478
491
throw new EvalException ("Starlark computation cancelled: too many steps" );
479
492
}
493
+ CoverageRecorder .getInstance ().recordCoverage (expr );
480
494
481
495
// The switch cases have been split into separate functions
482
496
// to reduce the stack usage during recursion, which is
@@ -533,9 +547,17 @@ private static Object evalBinaryOperator(StarlarkThread.Frame fr, BinaryOperator
533
547
// AND and OR require short-circuit evaluation.
534
548
switch (binop .getOperator ()) {
535
549
case AND :
536
- return Starlark .truth (x ) ? eval (fr , binop .getY ()) : x ;
550
+ if (Starlark .truth (x )) {
551
+ return eval (fr , binop .getY ());
552
+ }
553
+ CoverageRecorder .getInstance ().recordVirtualJump (binop );
554
+ return x ;
537
555
case OR :
538
- return Starlark .truth (x ) ? x : eval (fr , binop .getY ());
556
+ if (Starlark .truth (x )) {
557
+ CoverageRecorder .getInstance ().recordVirtualJump (binop );
558
+ return x ;
559
+ }
560
+ return eval (fr , binop .getY ());
539
561
default :
540
562
Object y = eval (fr , binop .getY ());
541
563
try {
@@ -577,7 +599,9 @@ private static Object evalDict(StarlarkThread.Frame fr, DictExpression dictexpr)
577
599
private static Object evalDot (StarlarkThread .Frame fr , DotExpression dot )
578
600
throws EvalException , InterruptedException {
579
601
Object object = eval (fr , dot .getObject ());
580
- String name = dot .getField ().getName ();
602
+ Identifier field = dot .getField ();
603
+ CoverageRecorder .getInstance ().recordCoverage (field );
604
+ String name = field .getName ();
581
605
try {
582
606
return Starlark .getattr (
583
607
fr .thread .mutability (), fr .thread .getSemantics (), object , name , /*defaultValue=*/ null );
@@ -627,6 +651,7 @@ private static Object evalCall(StarlarkThread.Frame fr, CallExpression call)
627
651
Object [] positional = npos == 0 ? EMPTY : new Object [npos ];
628
652
for (i = 0 ; i < npos ; i ++) {
629
653
Argument arg = arguments .get (i );
654
+ CoverageRecorder .getInstance ().recordCoverage (arg );
630
655
Object value = eval (fr , arg .getValue ());
631
656
positional [i ] = value ;
632
657
}
@@ -635,13 +660,15 @@ private static Object evalCall(StarlarkThread.Frame fr, CallExpression call)
635
660
Object [] named = n == npos ? EMPTY : new Object [2 * (n - npos )];
636
661
for (int j = 0 ; i < n ; i ++) {
637
662
Argument .Keyword arg = (Argument .Keyword ) arguments .get (i );
663
+ CoverageRecorder .getInstance ().recordCoverage (arg );
638
664
Object value = eval (fr , arg .getValue ());
639
665
named [j ++] = arg .getName ();
640
666
named [j ++] = value ;
641
667
}
642
668
643
669
// f(*args) -- varargs
644
670
if (star != null ) {
671
+ CoverageRecorder .getInstance ().recordCoverage (star );
645
672
Object value = eval (fr , star .getValue ());
646
673
if (!(value instanceof StarlarkIterable )) {
647
674
fr .setErrorLocation (star .getStartLocation ());
@@ -656,6 +683,7 @@ private static Object evalCall(StarlarkThread.Frame fr, CallExpression call)
656
683
657
684
// f(**kwargs)
658
685
if (starstar != null ) {
686
+ CoverageRecorder .getInstance ().recordCoverage (starstar );
659
687
Object value = eval (fr , starstar .getValue ());
660
688
if (!(value instanceof Dict )) {
661
689
fr .setErrorLocation (starstar .getStartLocation ());
@@ -791,6 +819,7 @@ void execClauses(int index) throws EvalException, InterruptedException {
791
819
assign (fr , forClause .getVars (), elem );
792
820
execClauses (index + 1 );
793
821
}
822
+ CoverageRecorder .getInstance ().recordVirtualJump (clause );
794
823
} catch (EvalException ex ) {
795
824
fr .setErrorLocation (forClause .getStartLocation ());
796
825
throw ex ;
@@ -802,12 +831,15 @@ void execClauses(int index) throws EvalException, InterruptedException {
802
831
Comprehension .If ifClause = (Comprehension .If ) clause ;
803
832
if (Starlark .truth (eval (fr , ifClause .getCondition ()))) {
804
833
execClauses (index + 1 );
834
+ } else {
835
+ CoverageRecorder .getInstance ().recordVirtualJump (clause );
805
836
}
806
837
}
807
838
return ;
808
839
}
809
840
810
841
// base case: evaluate body and add to result.
842
+ CoverageRecorder .getInstance ().recordCoverage (comp .getBody ());
811
843
if (dict != null ) {
812
844
DictExpression .Entry body = (DictExpression .Entry ) comp .getBody ();
813
845
Object k = eval (fr , body .getKey ());
0 commit comments