Skylark debugger: Fix NPE listing frames.
Environment$Continuation#caller is most definitely nullable in practice.
I suspect it's a bug in skylark itself, but for now, just properly mark
it nullable and handle it in the debugger.
Stack trace from NPE:
Caused by: java.lang.NullPointerException
at com.google.devtools.build.lib.syntax.Environment.listFrames(Environment.java:1197)
at com.google.devtools.build.lib.syntax.Environment.listFrames(Environment.java:81)
at com.google.devtools.build.lib.skylarkdebug.server.ThreadHandler.listFrames(ThreadHandler.java:236)
at com.google.devtools.build.lib.skylarkdebug.server.ThreadHandler.getThreadProto(ThreadHandler.java:345)
at com.google.devtools.build.lib.skylarkdebug.server.ThreadHandler.pauseCurrentThread(ThreadHandler.java:289)
at com.google.devtools.build.lib.skylarkdebug.server.ThreadHandler.pauseIfNecessary(ThreadHandler.java:203)
at com.google.devtools.build.lib.skylarkdebug.server.SkylarkDebugServer.pauseIfNecessary(SkylarkDebugServer.java:158)
at com.google.devtools.build.lib.skylarkdebug.server.SkylarkDebugServer$DebugAwareEval.exec(SkylarkDebugServer.java:262)
at com.google.devtools.build.lib.syntax.UserDefinedFunction.call(UserDefinedFunction.java:91)
at com.google.devtools.build.lib.syntax.BaseFunction.callWithArgArray(BaseFunction.java:462)
at com.google.devtools.build.lib.syntax.BaseFunction.call(BaseFunction.java:440)
at com.google.devtools.build.lib.analysis.skylark.SkylarkRuleConfiguredTargetUtil.lambda$buildRule$1(SkylarkRuleConfiguredTargetUtil.java:105)
at com.google.devtools.build.lib.skylarkdebug.server.SkylarkDebugServer.runWithDebugging(SkylarkDebugServer.java:142)
at com.google.devtools.build.lib.syntax.DebugServerUtils.runWithDebuggingIfEnabled(DebugServerUtils.java:70)
at com.google.devtools.build.lib.analysis.skylark.SkylarkRuleConfiguredTargetUtil.buildRule(SkylarkRuleConfiguredTargetUtil.java:100)
PiperOrigin-RevId: 200229036
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
index 6f84188..5b22906 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
@@ -463,7 +463,7 @@
final BaseFunction function;
/** The {@link FuncallExpression} to which this Continuation will return. */
- final FuncallExpression caller;
+ @Nullable final FuncallExpression caller;
/** The next Continuation after this Continuation. */
@Nullable final Continuation continuation;
@@ -478,12 +478,12 @@
@Nullable final LinkedHashSet<String> knownGlobalVariables;
Continuation(
- Continuation continuation,
+ @Nullable Continuation continuation,
BaseFunction function,
- FuncallExpression caller,
+ @Nullable FuncallExpression caller,
LexicalFrame lexicalFrame,
GlobalFrame globalFrame,
- LinkedHashSet<String> knownGlobalVariables) {
+ @Nullable LinkedHashSet<String> knownGlobalVariables) {
this.continuation = continuation;
this.function = function;
this.caller = caller;
@@ -719,13 +719,17 @@
/**
* Enters a scope by saving state to a new Continuation
+ *
* @param function the function whose scope to enter
* @param lexical the lexical frame to use
* @param caller the source AST node for the caller
* @param globals the global Frame that this function closes over from its definition Environment
*/
void enterScope(
- BaseFunction function, LexicalFrame lexical, FuncallExpression caller, GlobalFrame globals) {
+ BaseFunction function,
+ LexicalFrame lexical,
+ @Nullable FuncallExpression caller,
+ GlobalFrame globals) {
continuation =
new Continuation(
continuation, function, caller, lexicalFrame, globalFrame, knownGlobalVariables);
@@ -1194,7 +1198,8 @@
.build());
currentFrame = currentContinuation.lexicalFrame;
- currentLocation = currentContinuation.caller.getLocation();
+ currentLocation =
+ currentContinuation.caller != null ? currentContinuation.caller.getLocation() : null;
currentContinuation = currentContinuation.continuation;
}