Skip to content

Preserve user .vscode/extensions.json on IDE regeneration (#5473)#5474

Open
tillig wants to merge 1 commit into
platformio:developfrom
tillig:feature/issue-5473
Open

Preserve user .vscode/extensions.json on IDE regeneration (#5473)#5474
tillig wants to merge 1 commit into
platformio:developfrom
tillig:feature/issue-5473

Conversation

@tillig

@tillig tillig commented Jul 10, 2026

Copy link
Copy Markdown

Description

Fixes #5473.

Regenerating the VSCode integration (pio project init --ide vscode, which the VSCode extension triggers on every IntelliSense index rebuild) unconditionally overwrote an existing .vscode/extensions.json from a template. This had two consequences:

  1. Loss of user customization / VCS churn. The file was re-rendered from the template on every rebuild, reverting the user's ordering, formatting, and comments, and rewriting the file even when nothing had semantically changed.
  2. Silent data loss. The template merged the existing file by stripping comments with re.sub(r"^\s*//.*$", ...) (full-line // only) and then json.loads. An inline // or /* */ block comment (both valid JSONC, which VSCode supports for this file) left invalid JSON, json.loads raised ValueError, and except ValueError: pass swallowed it — collapsing recommendations back to just the PlatformIO default and deleting the user's own recommendations.

Changes

  • New helper platformio/project/integration/jsonc.py — minimal JSONC support: comment/trailing-comma-tolerant loads(), and ensure_array_items() which inserts missing array entries in place, preserving the surrounding comments, ordering, and formatting.
  • ProjectGenerator._merge_contents — for extensions.json, when the file already exists the required entries are inserted in place; the file is only rewritten when an entry is actually added. If the existing file cannot be parsed as JSONC, it safely falls back to regenerating from the template. When the file is absent, it is scaffolded from the template as before. Other generated files (c_cpp_properties.json, launch.json) are unaffected and still regenerate.
  • Template simplified to a static scaffold (the parse/merge logic now lives in code).
  • Tests — unit tests for the JSONC helper (comments, block comments, trailing commas, comment markers inside strings, empty arrays, missing keys, no-op when already present, invalid input) and end-to-end project init --ide vscode tests covering (a) an existing customized file left byte-for-byte unchanged on re-run and (b) a missing recommendation inserted while the user's inline comment and existing entry survive.
  • HISTORY.rst entry under 6.2.0.

Why a hand-rolled JSONC helper instead of a dependency?

The problem is not parsing JSONC — it's editing it in place without destroying the user's comments. Standard JSONC parsers (json5, pyjson5, commentjson, hjson) only parse to a Python object; comments do not survive into the parsed result, so a load → mutate → dump round-trip would reintroduce the exact data loss this PR fixes. Comment-preserving round-trip editing of JSONC has no established Python library (unlike ruamel.yaml for YAML). Since a parser dependency wouldn't remove the need for the in-place insertion logic — and PlatformIO keeps its dependency set intentionally small — the helper parses only to decide whether an entry is missing, then performs a surgical string insertion into the original text, leaving every other byte untouched. It is pure-Python, has no I/O, and is covered by unit tests. Happy to swap in a maintainer-preferred approach if you'd rather.

Checklist

  • make before-commit (codespell, isort, black, pylint) passes on the changed files (pylint 10.00/10)
  • Tests added and passing
  • CLA signed

…#5473)

Regenerating the VSCode integration overwrote an existing
.vscode/extensions.json from a template on every index rebuild,
reverting the user's ordering, formatting, and comments. Worse, the
merge only stripped full-line // comments before json.loads, so inline
or block comments made parsing fail silently (except ValueError: pass)
and the user's recommendation entries were dropped entirely.

Add a small JSONC helper (comment- and trailing-comma-tolerant parsing
plus in-place array insertion) and use it in ProjectGenerator so that,
when extensions.json already exists, the required entries are inserted
in place without touching anything else. The file is only rewritten when
an entry is actually added. When the file is absent, it is still
scaffolded from the (now static) template.

Add unit tests for the JSONC helper and end-to-end init tests covering
the preserve-on-rerun and insert-missing-with-comments cases.
@CLAassistant

CLAassistant commented Jul 10, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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.

project init --ide vscode unconditionally overwrites .vscode/extensions.json, destroying user ordering, formatting, and comments

2 participants