Skip to content

Conversation

@farmaazon
Copy link
Contributor

Pull Request Description

Fixes #14094

Screencast.From.2025-11-28.15-13-35.mp4

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.
  • [ ] If meaningful changes were made to logic or tests affecting Enso Cloud integration in the libraries,
    or the Snowflake database integration, a run of the Extra Tests has been scheduled.
    • If applicable, it is suggested to paste a link to a successful run of the Extra Tests.

Comment on lines 19 to 38
const findMainSourceOf = (selectedNode: NodeId) => {
const findResult = (): Identifier | None => {
const alreadyKnown = knownMainSourceIdentifier.get(selectedNode)
if (alreadyKnown) return alreadyKnown
const selfPort = graphDb.nodeIdToNode.get(selectedNode)?.primaryApplication.selfArgument
if (!selfPort) return none
const mainSourceId = set.first(graphDb.connections.reverseLookup(selfPort))
if (!mainSourceId) return none
const mainSourceNode = graphDb.getPatternExpressionNodeId(mainSourceId)
if (mainSourceNode && selected.has(mainSourceNode)) {
return findMainSourceOf(mainSourceNode)
} else {
const ident = graphDb.getOutputPortIdentifier(mainSourceId)
return ident != null && isIdentifier(ident) ? ident : none
}
}
const result = findResult()
knownMainSourceIdentifier.set(selectedNode, result)
return result
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kazcw I considered your comment in #14325 (comment) but sorting here would require bringing method function too (with guarantee that this is same method as graphDb), so I prefer to keep this, more self-contained solution.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think my proposed approach would introduce any greater reliance on the current method state than is already implicit in the use of graphDb.connections?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I meant having two arguments (code and graphDb) where the caller would responsible for making sure they refer to same method.

But now I realized, this problem may be easily avoided by providing just the graph store.

Comment on lines 12 to 13
* input connection. If any connection could not be subsituted this way (e.g. no connection to self-port),
* an empty array will be returned.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think an empty array is a bit subtle of a way to express an error condition probably needs to be reported to the user

Comment on lines 19 to 38
const findMainSourceOf = (selectedNode: NodeId) => {
const findResult = (): Identifier | None => {
const alreadyKnown = knownMainSourceIdentifier.get(selectedNode)
if (alreadyKnown) return alreadyKnown
const selfPort = graphDb.nodeIdToNode.get(selectedNode)?.primaryApplication.selfArgument
if (!selfPort) return none
const mainSourceId = set.first(graphDb.connections.reverseLookup(selfPort))
if (!mainSourceId) return none
const mainSourceNode = graphDb.getPatternExpressionNodeId(mainSourceId)
if (mainSourceNode && selected.has(mainSourceNode)) {
return findMainSourceOf(mainSourceNode)
} else {
const ident = graphDb.getOutputPortIdentifier(mainSourceId)
return ident != null && isIdentifier(ident) ? ident : none
}
}
const result = findResult()
knownMainSourceIdentifier.set(selectedNode, result)
return result
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think my proposed approach would introduce any greater reliance on the current method state than is already implicit in the use of graphDb.connections?

for (const { port, ident } of detachInfo.value) {
const result = await graphStore.updatePortValue(port, Ast.Ident.new(edit, ident), edit)
if (!result.ok) {
result.error.log('Failed to connect around')
Copy link
Contributor

Choose a reason for hiding this comment

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

We should expect this case to be reachable, as we have awaited during this edit and arbitrary graph edits may have taken place since the detachInfo analysis was performed. As such, we should carefully consider error recovery. I think maybe the best we could do is: Notify the user (e.g. with a toast) that an error occurred during the operation, and they may Undo if the result is wrong.

I think I've said this before, but I really don't like the complexity that results from allowing the edit operations to be async. It makes it so much harder to avoid bugs and crashes in hard-to-predict-or-test cases where multiple operations interact.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a toast. AFAIK this async edit was needed in signature editor. I will make a task for sorting this out, as I agree async edits are very troublesome.


for (const [source, targets] of graphDb.connections.allForward()) {
for (const target of targets) {
// TODO[ao]: copied from collapsing.ts. Worth merging?
Copy link
Contributor

Choose a reason for hiding this comment

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

TODO in code--let's create an issue (or add it to an existing issue) if it isn't addressed in this PR

@farmaazon farmaazon requested a review from kazcw December 2, 2025 14:01
}),
)
if (results.some((result) => !result.ok)) {
toasts.userActionFailed.show('Failed to connect removed component around')
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should be more clear that the action was attempted anyway, rather than aborted--something like "Errors occurred while connecting around removed components"

@farmaazon farmaazon added the CI: Ready to merge This PR is eligible for automatic merge label Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: Ready to merge This PR is eligible for automatic merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add delete and connect around for components

3 participants