镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Add support for disabling/enabling blocks with roundtrip comment preservation (#10042) - #11699

Open
Dmitriy Antipov (THEb0nny) wants to merge 3 commits into
microsoft:masterfrom
THEb0nny:feature/disable-blocks
Open

Dmitriy Antipov (THEb0nny) wants to merge 3 commits into
microsoft:masterfrom
THEb0nny:feature/disable-blocks

Conversation

@THEb0nny

@THEb0nny Dmitriy Antipov (THEb0nny) commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Improvement #10042

Summary

This PR implements block disabling/enabling in MakeCode with seamless roundtrip preservation across Blocks, TypeScript, and Python:

  1. Context Menu & Workspace Support:

    • Enables Blockly's disable: true workspace option.
    • Registers the blockDisable context menu entry ("Disable Block" / "Enable Block") with telemetry.
    • Patches legacy blocks so that only explicitly user-disabled blocks (MANUALLY_DISABLED) remain disabled.
  2. Code Generation (Blocks -> TS / Python):

    • Disabled statement blocks emit clean natural comments: // ... in TypeScript and # ... in Python without custom symbols or prefixes.
    • Multi-line statements (like if, while, loops) and top-level event blocks properly comment out their entire subtrees.
    • Prevents duplicate comment prefixes when a block already has an attached block comment (avoiding // // in TS and # // in Python).
  3. Decompilation (TS / Python -> Blocks):

    • Distinguishes commented-out code from human notes: parses comments using isBlockCode and converts valid MakeCode statement code to disabled blocks (disabled="true" disabled-reasons="MANUALLY_DISABLED").
    • Human text notes (e.g. // TODO: ..., // Note: ..., sentences) remain preserved as comment notes / sticky notes.
    • Trailing comments at the end of Python files are now preserved when converting to TypeScript (py2ts) instead of being dropped.
  4. Variable Handling:

    • Fixes variable hoisting and duplication: leftoverVars only emits declarations for variables actively referenced in enabled blocks (v.firstReference && v.firstReference.isEnabled()).
    • Disabled variable setters (e.g. // let y = 0) stay in their original position without duplicating or swapping order with other variables.
  5. Upstream Bug Fix:

    • Fixed TypeError: Cannot read properties of undefined (reading 'splice') in pxtcompiler/emitter/decompiler.ts when ownerStatement.comment is undefined.

Verification & Testing

  • All 166 decompiler tests pass (npm run test:decompiler / gulp testdecompiler).
  • All 26 Python decompiler tests pass (gulp testpydecomp).
  • Verified roundtrips in pxt-microbit editor:
    • Disabling action blocks (led.plot, basic.showNumber).
    • Switching Blocks ⇄ TypeScript ⇄ Python.
    • Adding/editing comments on disabled blocks.
    • Disabling variables without reordering or duplication.

…crosoft#10042)

- Code Generation (Blocks -> TS / Python):
  - In pxtblocks/compiler/compiler.ts: emit disabled statement blocks as
    commented-out code using '//' for TypeScript and '#' for Python.
  - In commentOutJsNodes: check if line is already commented to avoid
    duplicating prefixes ('// //' in TS and '# //' in Python).
  - Update leftoverVars to only emit variable declarations for variables
    actively referenced in enabled blocks (v.firstReference &&
    v.firstReference.isEnabled()), preventing variable duplication and
    preserving declaration order when variable initializers are disabled.
  - Guard binding.alreadyDeclared, isAssigned, and firstReference in
    compileSet and compileVariableGet when blocks are disabled.

- Decompilation (TS / Python -> Blocks):
  - In pxtcompiler/emitter/decompiler.ts: add disabled flag to BlockNode
    and StatementNode; emit disabled="true" disabled-reasons="MANUALLY_DISABLED"
    in openBlockTag.
  - Add isBlockCode and preprocessDisabledBlocks to distinguish valid
    MakeCode statements from human comments (TODOs, notes). Valid code is
    marked with /*__disabled__*/ and decompiled into disabled blocks,
    while human comments remain comment sticky notes.
  - Hook preprocessDisabledBlocks into decompile operations in service.ts,
    driver.ts, and webapp compiler.ts.
  - Fix upstream MakeCode bug in getNodeComments where comment.splice threw
    when ownerStatement.comment was undefined.

- Python Support:
  - In pxtpy/parser.ts: preserve trailing comments at the end of the file
    by emitting a Pass statement with attached comments when currComments
    remains at EOF.

- Typings:
  - Add preprocessDisabledBlocks?: boolean to CompileOptions in
    localtypings/pxtarget.d.ts.
@THEb0nny
Dmitriy Antipov (THEb0nny) marked this pull request as draft October 28, 2026 00:23
@THEb0nny

Copy link
Copy Markdown
Contributor Author
Microsoft.MakeCode.for.micro_bit.-.Google.Chrome.2026-10-28.03-11-33-compressed.mp4

…oft#10042)

Enable bidirectional translation of commented-out code statements when switching between TypeScript and Python in the editor:

- TS -> Python (pydecompiler.ts, service.ts): run preprocessDisabledBlocks during pydecompile to convert commented-out statements into AST nodes tagged with /*__disabled__*/, and prefix the transpiled Python statement with '# '. This ensures identifiers and casing (e.g. motors.largeB.run -> motors.large_b.run, booleans true -> True) are properly converted to Python syntax.
- Python -> TS (converter.ts, parser.ts, ast.ts): detect and parse comment statements (calls, assignments) into AST statements tagged with _disabled, transpile them to TypeScript, and emit them prefixed with '// '. Suppress diagnostics on disabled statements during typechecking passes so commented code does not block conversion.
- Preserve non-code human comments unmodified in both directions.
@THEb0nny

Dmitriy Antipov (THEb0nny) commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Update: Bidirectional translation for commented-out code statements between TypeScript and Python

When disabling blocks or commenting out code in the text editor, switching between TypeScript and Python previously retained the commented text verbatim (e.g. // motors.largeB.run(50) remained # motors.largeB.run(50) instead of adapting to Python's naming conventions and syntax).

This commit adds bidirectional statement transpilation for commented-out code:

  1. TypeScript → Python (pydecompiler.ts, service.ts):

    • service.ts runs preprocessDisabledBlocks during pydecompile, parsing commented-out code statements as AST nodes with a leading /*__disabled__*/ marker.
    • pydecompiler.ts transpiles the statement with standard Python naming and casing (e.g., motors.largeB.run(50) $\to$ motors.large_b.run(50)), strips the internal marker, and prefixes the emitted Python code with # .
    • Regular human notes/comments remain untouched.
  2. Python → TypeScript (converter.ts, parser.ts, ast.ts):

    • During Python AST parsing, single-line comments representing executable statements (method/function calls, assignments) are identified and converted into AST statement nodes tagged with _disabled = true.
    • In toTS(), these statements are transpiled to TypeScript syntax (e.g., # motors.large_b.run(50) $\to$ motors.largeB.run(50)).
    • converter.ts:stmt() emits _disabled statements wrapped with // .
    • Diagnostic errors for _disabled statements are suppressed so disabled or deprecated code does not block project conversion.
    • Non-code human notes (# TODO, explanations) remain regular comments without changes.
  3. Roundtrip with Blocks:

    • Commented statements seamlessly roundtrip across Blocks $\leftrightarrow$ TypeScript $\leftrightarrow$ Python without losing block disable state or breaking when uncommented in either language.

@THEb0nny

Copy link
Copy Markdown
Contributor Author
BrickCode.for.EV3.-.Google.Chrome.2026-10-28.22-16-38-compressed.mp4

@THEb0nny
Dmitriy Antipov (THEb0nny) marked this pull request as ready for review October 28, 2026 20:06
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.

1 participant