From 080690b3ad2515c8a9c4ba8f3fb2aea09e969c79 Mon Sep 17 00:00:00 2001 From: Michael Mauderer Date: Wed, 17 Jan 2024 10:18:40 +0000 Subject: [PATCH] Fix for code enabling/disabling output context on single node (#8776) --- .../src/components/GraphEditor/GraphNode.vue | 33 +++++++++---------- app/gui2/src/util/ast/__tests__/match.test.ts | 7 ++++ app/gui2/src/util/ast/match.ts | 10 +++++- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/app/gui2/src/components/GraphEditor/GraphNode.vue b/app/gui2/src/components/GraphEditor/GraphNode.vue index 77aa4132f8b..9b0b9acec1f 100644 --- a/app/gui2/src/components/GraphEditor/GraphNode.vue +++ b/app/gui2/src/components/GraphEditor/GraphNode.vue @@ -179,24 +179,23 @@ const isOutputContextOverridden = computed({ set(shouldOverride) { const module = projectStore.module if (!module) return - const replacements = shouldOverride - ? [Ast.TextLiteral.new(projectStore.executionMode)] - : undefined const edit = props.node.rootSpan.module.edit() - const newAst = prefixes.modify( - edit, - props.node.rootSpan, - projectStore.isOutputContextEnabled - ? { - enableOutputContext: undefined, - disableOutputContext: replacements, - } - : { - enableOutputContext: replacements, - disableOutputContext: undefined, - }, - ) - graph.setNodeContent(props.node.rootSpan.exprId, newAst.code()) + const replacementText = shouldOverride + ? [Ast.TextLiteral.new(projectStore.executionMode, edit)] + : undefined + const replacements = projectStore.isOutputContextEnabled + ? { + enableOutputContext: undefined, + disableOutputContext: replacementText, + } + : { + enableOutputContext: replacementText, + disableOutputContext: undefined, + } + const expression = props.node.rootSpan + const newAst = prefixes.modify(edit, expression, replacements) + const code = newAst.code() + graph.setNodeContent(props.node.rootSpan.exprId, code) }, }) diff --git a/app/gui2/src/util/ast/__tests__/match.test.ts b/app/gui2/src/util/ast/__tests__/match.test.ts index a7f1fc8b93c..9c8a8eb3ca6 100644 --- a/app/gui2/src/util/ast/__tests__/match.test.ts +++ b/app/gui2/src/util/ast/__tests__/match.test.ts @@ -106,4 +106,11 @@ test.each([ const intron = Ast.parse(source, edit) const instantiated = pattern.instantiate(edit, [intron.exprId]) expect(instantiated.code(edit)).toBe(result) + + // Check that `instantiate` has not affected the base module. + const intron2 = Ast.parse(source, edit) + const originalParent = intron2.parent + const edit2 = edit.edit() + pattern.instantiate(edit2, [intron2.exprId]) + expect(edit.get(intron2.exprId)!.parent).toBe(originalParent) }) diff --git a/app/gui2/src/util/ast/match.ts b/app/gui2/src/util/ast/match.ts index 85621cc40f3..5baccf09a46 100644 --- a/app/gui2/src/util/ast/match.ts +++ b/app/gui2/src/util/ast/match.ts @@ -1,3 +1,4 @@ +import { assert } from '@/util/assert' import { Ast } from '@/util/ast' import { MutableModule } from '@/util/ast/abstract' @@ -44,7 +45,14 @@ export class Pattern { for (const matched of placeholders(ast, this.placeholder)) { const replacement = subtrees.shift() if (replacement === undefined) break - edit.get(replacement)!.parent = matched.parent + const replacementAst = edit.splice(edit.get(replacement)) + if (replacementAst === null) { + console.error( + 'Subtree ID provided to `instantiate` is not accessible in the `edit` module.', + ) + continue + } + replacementAst.parent = matched.parent matched.ref.node = replacement } return ast