Repository navigation
Address Gemini feedback about handling falsy values - #6077
Conversation
There was a problem hiding this comment.
Code Review
This pull request improves the handling of optional and empty inputs for string and number fields in the interactive language client form. Specifically, it refines truthiness checks to explicitly check for undefined and null, and updates the number input validation and return values to correctly handle empty or canceled inputs. A review comment suggests further refining the string input handling to safely convert null values to undefined to prevent potential type violations and runtime issues with InputBoxOptions.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| return await vscode.window.showInputBox({ | ||
| prompt: field.description, | ||
| value: prevAnswer ? prevAnswer : field.default, | ||
| value: prevAnswer !== undefined ? prevAnswer : field.default, |
There was a problem hiding this comment.
If prevAnswer or field.default is null (which can happen for optional fields), passing it directly to value will violate the InputBoxOptions type definition (which expects string | undefined) and may cause runtime issues or display "null" in the input box.
We should safely handle null values by converting them to undefined so that the input box remains empty.
| value: prevAnswer !== undefined ? prevAnswer : field.default, | |
| value: (prevAnswer !== undefined && prevAnswer !== null) ? prevAnswer : (prevAnswer === null ? undefined : (field.default ?? undefined)), |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## interactive-forms #6077 +/- ##
=====================================================
- Coverage 70.02% 70.00% -0.03%
=====================================================
Files 173 173
Lines 13265 13271 +6
Branches 2665 2668 +3
=====================================================
+ Hits 9289 9290 +1
- Misses 3480 3485 +5
Partials 496 496 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| } | ||
| if (numResult.trim() === '') { | ||
| return null; // null = empty (eg. not answering optional question) | ||
| } |
There was a problem hiding this comment.
@h9jiang hmm, now I'm wondering about this more... If we return null here, should it be added to formAnswers or skipped?
If we say null is used as a signal here to mean "no answer" and then we skip adding it to formAnswers, should the same apply to string fields submitted as an empty string? It might be odd to include those in formAnswers if not doing the same for numbers.
There was a problem hiding this comment.
Hi Danny, how about a button on the right top corner like this: (note the -> on the right top corner)
We could use this button to say, user can skip this question and we only render this button when the question is "optional". And if the user hit enter (even it is empty, since empty string is still a valid string), we interpret user intention as an answer so we run our client side validation. (like if this is really a number...) If user hit the skip button then, we consider this as a skip operation and the client will not send this answer to the client.
The following code is generated by Gemini and it seems to meet the requirement. However, we can only render this button for "inputBox" and "quickPick" (which covers every kinds of question except for "file"). IMO, the "ideal" file picker is the native built Quick Open using hot key cmd + p that allows user to fuzzy matching files they are looking for, and this would have support for rendering a "skip" button.
case 'string':
return new Promise<string | null | undefined>((resolve) => {
const inputBox = vscode.window.createInputBox();
inputBox.prompt = field.description;
inputBox.placeholder = field.description;
inputBox.value = prevAnswer !== undefined ? prevAnswer : field.default || '';
inputBox.ignoreFocusOut = true;
// 1. Create a custom "Next / Skip" button if the field is not required
const skipButton: vscode.QuickInputButton = {
iconPath: new vscode.ThemeIcon('arrow-right'),
tooltip: 'Skip / Next'
};
if (!field.required) {
inputBox.buttons = [skipButton];
}
// 2. Handle button clicks
inputBox.onDidTriggerButton((button) => {
if (button === skipButton) {
// Return null to signify "skipped / not answered"
resolve(null);
inputBox.hide();
}
});
// Handle standard submission (Enter key)
inputBox.onDidAccept(() => {
resolve(inputBox.value);
inputBox.hide();
});
// Handle cancellation (Escape key)
inputBox.onDidHide(() => {
resolve(undefined); // undefined signifies user cancelled the entire flow
inputBox.dispose();
});
inputBox.show();
});
We will have to make a little bit more change to render the skip button conditionally based on the "required" field but shouldn't be complicated. What do you think?
There was a problem hiding this comment.
(edit: this comment was posted before the one above was submitted, so it's out of order and I hadn't read it at the time!)
@h9jiang not urgent, just in case you missed it.. this is a question about how to represent skipped optional answers - if you press <enter> on a string input we might get empty string, not null, but on numbers we would presumably want to use null, which feels inconsistent. I think we should specify something so servers/clients agree.
There was a problem hiding this comment.
Hi, what I meant was, as long as user hit <enter> we will consider it as an input even it is empty.
In this case, if the user hit <enter> on a string input, we will consider it as an empty string answer. If the user hit <enter> on a number input, we will consider invalid.
If the user want to skip the question, either for string or number, user should click the -> arrow button. The arrow button is only available for optional questions. What do you think?
There was a problem hiding this comment.
I like the idea, but I do wonder if the -> icon is too subtle. Is there any real benefit to distinguishing between empty and skipped? (in a "full dialog" client, I don't imagine this distinction would be made). I also don't imagine that a "required string" field would expect to accept an empty string as a valid supplied value.
So what about just treating any empty inputs as unanswered/skipped? If they are required, they will be rejected during validation and the user forced to provide a value (ofc, if there was a default already entered, pressing <enter> would just have submitted that as the actual value).
There was a problem hiding this comment.
Hi @DanTup
I do wonder if the -> icon is too subtle.
I think you are correct, this is probably too subtle. I don't have a strong opinion on this, I think what you have described is also very reasonable.
The way I approached this problem is trying to eliminate ambiguity. I don't like "ambiguous" UI or special/default interpretation. But as you mentioned, the UI for -> is just too subtle.
So I would say, comparing between both solutions, the proposal you got is more user friendly. Let's go with that!
2a3c2bf to
14fbd9f
Compare
3c83172 to
28f3455
Compare
14fbd9f to
45e5e7d
Compare
45e5e7d to
aa8b70a
Compare
h9jiang
left a comment
There was a problem hiding this comment.
I think this is reasonable.
As you have suggested, we should not really expect a question that accept empty string as input. It make sense to interpret empty as zero value for required field, skip for optional field.
Thanks Danny.
I actually think we should not treat empty as zero for numerics either - if a numeric is required and has no default, we should treat empty the same as an invalid number, and force the user to type 0 if that's what they want? (of course, if zero is a reasonable default, the server can provide it as such). WDYT? |
aa8b70a to
6be4299
Compare
|
@h9jiang I'll merge this as-is (into the I think probably I'll merge the |
I agree. We have a way to indicate that a value isn't required because there's a reasonable default value. We also need a way to indicate that a value is required because there's no reasonable default. Allowing blank to mean Strings are similar. I haven't been following closely (the quoted comment just caught my eye), so I don't know what the current state is, but I'd advocate for not allowing an empty string when a string is required. I think that makes more sense than not being able to distinguish between and empty string and no string. |
Yep, I agree. I'm just preparing a PR that adds some tests (I will CC you both shortly when it's all green and the AIs reviewers are happy!) and I noticed this wasn't handled, so it also addresses that (as well as applying validation to lists that was missed before). |
@h9jiang this is the only thing in Gemini's feedback that seemed like a an issue to me - handling of 0/empty for number/string fields (we could convert an empty submission into a 0, and convert a 0/empty back into the default).
I think these changes make sense, but I wonder if we should specify more explicitly how optional questions should be handled by the client?
For example with this change, I think we will submit
nullfor an "empty" submission of a Number field, but we would still submit an empty string for a String field. We could convert the empty string also to anull?