mirror of
https://github.com/enso-org/enso.git
synced 2024-11-23 16:18:23 +03:00
Fix intermittent deletion failures (#10888) - Fix bug in deletion logic (the `syncModule` itself was passed to a function that tried to commit it as an edit) - Refactor APIs to avoid similar bugs (remove `direct` edit option) # Important Notes - `graphStore.getMutable` provides safer access to some of the functionality that was exposed by `direct` editing. - `graphStore.transact` has been eliminated; it was redundant with `graphStore.batchEdits`.
This commit is contained in:
parent
bd5ab43cf6
commit
92995d191f
@ -24,7 +24,7 @@ const editedNodeInitialColors = new Map<NodeId, string | undefined>()
|
|||||||
|
|
||||||
function setColor(color: string | undefined) {
|
function setColor(color: string | undefined) {
|
||||||
currentColor.value = color
|
currentColor.value = color
|
||||||
graphStore.transact(() => {
|
graphStore.batchEdits(() => {
|
||||||
if (color) {
|
if (color) {
|
||||||
for (const node of selection.selected) {
|
for (const node of selection.selected) {
|
||||||
if (!editedNodeInitialColors.has(node))
|
if (!editedNodeInitialColors.has(node))
|
||||||
|
@ -336,7 +336,7 @@ const graphBindingsHandler = graphBindings.handler({
|
|||||||
selected,
|
selected,
|
||||||
(id) => graphStore.db.nodeIdToNode.get(id)?.vis?.visible === true,
|
(id) => graphStore.db.nodeIdToNode.get(id)?.vis?.visible === true,
|
||||||
)
|
)
|
||||||
graphStore.transact(() => {
|
graphStore.batchEdits(() => {
|
||||||
for (const nodeId of selected) {
|
for (const nodeId of selected) {
|
||||||
graphStore.setNodeVisualization(nodeId, { visible: !allVisible })
|
graphStore.setNodeVisualization(nodeId, { visible: !allVisible })
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ function edgeInteractionClick(graphNavigator: GraphNavigator) {
|
|||||||
}
|
}
|
||||||
const target = graph.mouseEditedEdge.target ?? selection?.hoveredPort
|
const target = graph.mouseEditedEdge.target ?? selection?.hoveredPort
|
||||||
const targetNode = target && graph.getPortNodeId(target)
|
const targetNode = target && graph.getPortNodeId(target)
|
||||||
graph.transact(() => {
|
graph.batchEdits(() => {
|
||||||
if (source != null && sourceNode != targetNode) {
|
if (source != null && sourceNode != targetNode) {
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
if (graph.mouseEditedEdge?.disconnectedEdgeTarget != null)
|
if (graph.mouseEditedEdge?.disconnectedEdgeTarget != null)
|
||||||
|
@ -11,12 +11,7 @@ export function useAstDocumentation(graphStore: GraphStore, ast: ToValue<Ast | u
|
|||||||
const astValue = toValue(ast)
|
const astValue = toValue(ast)
|
||||||
if (!astValue) return
|
if (!astValue) return
|
||||||
if (value.trimStart() !== '') {
|
if (value.trimStart() !== '') {
|
||||||
graphStore.edit(
|
graphStore.getMutable(astValue).getOrInitDocumentation().setDocumentationText(value)
|
||||||
(edit) =>
|
|
||||||
edit.getVersion(astValue).getOrInitDocumentation().setDocumentationText(value),
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
// Remove the documentation node.
|
// Remove the documentation node.
|
||||||
const documented = astValue.documentingAncestor()
|
const documented = astValue.documentingAncestor()
|
||||||
|
@ -300,23 +300,19 @@ export const { injectFn: useGraphStore, provideFn: provideGraphStore } = createC
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteNodes(ids: Iterable<NodeId>) {
|
function deleteNodes(ids: Iterable<NodeId>) {
|
||||||
edit(
|
edit((edit) => {
|
||||||
(edit) => {
|
for (const id of ids) {
|
||||||
for (const id of ids) {
|
const node = db.nodeIdToNode.get(id)
|
||||||
const node = db.nodeIdToNode.get(id)
|
if (!node) continue
|
||||||
if (!node) continue
|
if (node.type !== 'component') continue
|
||||||
if (node.type !== 'component') continue
|
const usages = db.getNodeUsages(id)
|
||||||
const usages = db.getNodeUsages(id)
|
for (const usage of usages) updatePortValue(edit, usage, undefined)
|
||||||
for (const usage of usages) updatePortValue(edit, usage, undefined)
|
const outerExpr = edit.getVersion(node.outerExpr)
|
||||||
const outerExpr = edit.getVersion(node.outerExpr)
|
if (outerExpr) Ast.deleteFromParentBlock(outerExpr)
|
||||||
if (outerExpr) Ast.deleteFromParentBlock(outerExpr)
|
nodeRects.delete(id)
|
||||||
nodeRects.delete(id)
|
nodeHoverAnimations.delete(id)
|
||||||
nodeHoverAnimations.delete(id)
|
}
|
||||||
}
|
})
|
||||||
},
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNodeContent(
|
function setNodeContent(
|
||||||
@ -346,10 +342,6 @@ export const { injectFn: useGraphStore, provideFn: provideGraphStore } = createC
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function transact(fn: () => void) {
|
|
||||||
syncModule.value!.transact(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
const undoManager = {
|
const undoManager = {
|
||||||
undo() {
|
undo() {
|
||||||
proj.module?.undoManager.undo()
|
proj.module?.undoManager.undo()
|
||||||
@ -542,11 +534,9 @@ export const { injectFn: useGraphStore, provideFn: provideGraphStore } = createC
|
|||||||
*
|
*
|
||||||
* @param skipTreeRepair - If the edit is certain not to produce incorrect or non-canonical syntax, this may be set
|
* @param skipTreeRepair - If the edit is certain not to produce incorrect or non-canonical syntax, this may be set
|
||||||
* to `true` for better performance.
|
* to `true` for better performance.
|
||||||
* @param direct - Apply all changes directly to the synchronized module; they will be committed even if the callback
|
|
||||||
* exits by throwing an exception.
|
|
||||||
*/
|
*/
|
||||||
function edit<T>(f: (edit: MutableModule) => T, skipTreeRepair?: boolean, direct?: boolean): T {
|
function edit<T>(f: (edit: MutableModule) => T, skipTreeRepair?: boolean): T {
|
||||||
const edit = direct ? syncModule.value : syncModule.value?.edit()
|
const edit = syncModule.value?.edit()
|
||||||
assert(edit != null)
|
assert(edit != null)
|
||||||
let result
|
let result
|
||||||
edit.transact(() => {
|
edit.transact(() => {
|
||||||
@ -556,11 +546,18 @@ export const { injectFn: useGraphStore, provideFn: provideGraphStore } = createC
|
|||||||
assert(root instanceof Ast.BodyBlock)
|
assert(root instanceof Ast.BodyBlock)
|
||||||
Ast.repair(root, edit)
|
Ast.repair(root, edit)
|
||||||
}
|
}
|
||||||
if (!direct) syncModule.value!.applyEdit(edit)
|
syncModule.value!.applyEdit(edit)
|
||||||
})
|
})
|
||||||
return result!
|
return result!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Obtain a version of the given `Ast` for direct mutation. The `ast` must exist in the current module.
|
||||||
|
* This can be more efficient than creating and committing an edit, but skips tree-repair and cannot be aborted.
|
||||||
|
*/
|
||||||
|
function getMutable<T extends Ast.Ast>(ast: T): Ast.Mutable<T> {
|
||||||
|
return syncModule.value!.getVersion(ast)
|
||||||
|
}
|
||||||
|
|
||||||
function batchEdits(f: () => void, origin: Origin = defaultLocalOrigin) {
|
function batchEdits(f: () => void, origin: Origin = defaultLocalOrigin) {
|
||||||
assert(syncModule.value != null)
|
assert(syncModule.value != null)
|
||||||
syncModule.value.transact(f, origin)
|
syncModule.value.transact(f, origin)
|
||||||
@ -691,7 +688,6 @@ export const { injectFn: useGraphStore, provideFn: provideGraphStore } = createC
|
|||||||
})
|
})
|
||||||
|
|
||||||
return proxyRefs({
|
return proxyRefs({
|
||||||
transact,
|
|
||||||
db: markRaw(db),
|
db: markRaw(db),
|
||||||
mockExpressionUpdate,
|
mockExpressionUpdate,
|
||||||
editedNodeInfo,
|
editedNodeInfo,
|
||||||
@ -710,6 +706,7 @@ export const { injectFn: useGraphStore, provideFn: provideGraphStore } = createC
|
|||||||
pickInCodeOrder,
|
pickInCodeOrder,
|
||||||
ensureCorrectNodeOrder,
|
ensureCorrectNodeOrder,
|
||||||
batchEdits,
|
batchEdits,
|
||||||
|
getMutable,
|
||||||
overrideNodeColor,
|
overrideNodeColor,
|
||||||
getNodeColorOverride,
|
getNodeColorOverride,
|
||||||
setNodeContent,
|
setNodeContent,
|
||||||
|
Loading…
Reference in New Issue
Block a user