Skip to content

fix: avoid spurious 'restart terminal' prompts on every window reload#1648

Merged
wenytang-ms merged 3 commits into
mainfrom
fix/1647-avoid-terminal-restart-prompt
Jun 2, 2026
Merged

fix: avoid spurious 'restart terminal' prompts on every window reload#1648
wenytang-ms merged 3 commits into
mainfrom
fix/1647-avoid-terminal-restart-prompt

Conversation

@wenytang-ms
Copy link
Copy Markdown
Contributor

Summary

Fixes #1647: the Debugger for Java extension prompts the user to restart their terminal every time the VS Code window is reloaded, even when nothing about the contributed environment has actually changed.

Root cause

  • "src/noConfigDebugInit.ts" + runs on every activation and unconditionally:
  1. Calls + "collection.clear()" + on + "context.environmentVariableCollection" + .
  2. Re-adds + "VSCODE_JDWP_ADAPTER_ENDPOINTS" + , + "VSCODE_JAVA_EXEC" + , and a + "PATH" + append.

Fix

Introduce diff-aware helpers in src/envVarSync.ts:

  • applyReplaceIfChanged / applyAppendIfChanged — only call replace / append when the existing mutator's type, value, and normalized options differ from the desired ones.
  • deleteIfPresent — only call delete when a mutator exists.

Rewrite the activation flow in src/noConfigDebugInit.ts to use those helpers and drop the unconditional clear(). On a typical reload all comparisons are no-ops, so VS Code never observes a change and never prompts.

Behavioral notes

  • Java executable detection failures no longer wipe VSCODE_JAVA_EXEC. If getJavaHome() returns nothing (e.g., JDT LS hasn't finished initializing), we keep the previously stored value instead of deleting it, avoiding churn from transient startup hiccups.
  • One-time legacy cleanup: explicitly delete keys older versions used to set but no longer manage (currently just JAVA_TOOL_OPTIONS, per the comment that was already in this file). After the first reload this is also a no-op.
  • Description: set collection.description = Java No-Config Debug`` so the source is visible in VS Code's environment-variable UI.

Tests

Added test/envVarSync.test.ts with 13 cases covering:

  • write-on-missing, no-op-on-match, write-on-value-diff, write-on-options-diff
  • override across mutator types (Replace ↔ Append)
  • deleteIfPresent present/absent
  • a regression test simulating two back-to-back activations and asserting the second one performs zero writes — this is the exact scenario from Extension keeps requesting to restart my terminal #1647.

Full npm test output: 24 passing, 0 failing.

Risk

  • Scope is limited to the No-Config Debug activation path.
  • No public API surface changes; registerNoConfigDebug signature unchanged.
  • One-time prompt may still appear after upgrading to a version whose extPath differs (the PATH append value embeds the extension version directory) — this is unavoidable and only happens once per upgrade.

VS Code shows a 'restart terminal to apply environment variable changes'
prompt whenever an extension's EnvironmentVariableCollection differs from
what is already applied to running terminals. The previous No-Config
Debug activation flow called collection.clear() followed by replace() /
append() unconditionally, which VS Code always interprets as a change
even when the resulting values are byte-identical, so the prompt fired
on every window reload.

Refactor the activation to diff-aware helpers (applyReplaceIfChanged,
applyAppendIfChanged, deleteIfPresent) that only write to the collection
when the existing mutator's type, value, or options actually differ from
what we want. The hot path on a normal reload becomes a sequence of
no-op get() comparisons, so VS Code never observes a change and the
prompt no longer appears.

Additional notes:
* Compare normalized EnvironmentVariableMutatorOptions
  (applyAtProcessCreation / applyAtShellIntegration) so future options
  changes still trigger a write.
* When the Java Language Server cannot resolve a Java home, keep the
  previously stored VSCODE_JAVA_EXEC instead of deleting it, to avoid
  churn caused by transient startup failures.
* Explicitly clean up legacy keys (currently JAVA_TOOL_OPTIONS) that
  older versions of this extension used to set but no longer manage.
* Set a human-readable description on the collection so users can see
  the source in VS Code's environment variable UI.

Fixes #1647

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@wenytang-ms wenytang-ms changed the title Fix #1647: avoid spurious 'restart terminal' prompts on every window reload fix: avoid spurious 'restart terminal' prompts on every window reload Jun 2, 2026
@wenytang-ms wenytang-ms requested a review from Copilot June 2, 2026 03:03
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes #1647 by making the extension’s persistent EnvironmentVariableCollection updates idempotent, so VS Code doesn’t interpret every window reload as an environment change that requires restarting terminals.

Changes:

  • Added diff-aware helpers (applyReplaceIfChanged, applyAppendIfChanged, deleteIfPresent) to avoid writing to the environment collection when nothing effectively changes.
  • Updated no-config debug activation to stop calling collection.clear(), perform one-time legacy cleanup, and set a visible collection description.
  • Added unit tests covering mutator diffing behavior and a regression test for back-to-back activations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/envVarSync.ts Introduces idempotent environment-variable collection update helpers with option normalization.
src/noConfigDebugInit.ts Switches activation flow to diff-aware updates (no clear()), adds legacy cleanup + collection description.
test/envVarSync.test.ts Adds targeted unit/regression coverage ensuring repeated activations produce zero writes when unchanged.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/noConfigDebugInit.ts Outdated
JAVA_TOOL_OPTIONS has never been written to the per-extension EnvironmentVariableCollection by this codebase (verified via 'git log -S JAVA_TOOL_OPTIONS'). The legacy cleanup loop was therefore dead code, and could be misread as touching user-managed env vars (it cannot — the collection is per-extension and only sees mutators this extension wrote).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@wenytang-ms
Copy link
Copy Markdown
Contributor Author

Good catch — agreed, removed in bf7fff1.

To clarify why it was safe but still worth removing:

  • context.environmentVariableCollection is per-extension. collection.delete() only removes a mutator that this extension previously wrote; it can never touch a JAVA_TOOL_OPTIONS the user set in their shell profile, settings.json terminal.integrated.env.*, or another extension's collection.
  • I checked the history with git log -S JAVA_TOOL_OPTIONS -- src/noConfigDebugInit.ts — this extension has never called collection.replace('JAVA_TOOL_OPTIONS', ...). The only reference is the comment from feat: no config debug #1578 explaining why we deliberately don't set it. So the cleanup loop was dead code.

Since the value was effectively zero and the code reads as if it might be doing something risky, dropping it is the cleaner call. PR updated.

Production code no longer calls deleteIfPresent after the legacy cleanup loop was removed. Drop the helper and its tests rather than carry a YAGNI export — easy to reintroduce if a real caller appears.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@wenytang-ms wenytang-ms merged commit 9df1acb into main Jun 2, 2026
4 checks passed
@wenytang-ms wenytang-ms deleted the fix/1647-avoid-terminal-restart-prompt branch June 2, 2026 04:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extension keeps requesting to restart my terminal

4 participants