Merge pull request #2025 from xodio/fix-stale-output-terminals-without-links-below

Fix flatten: get rid of stale output custom type terminals
This commit is contained in:
Kirill Shumilov
2020-08-28 17:38:20 +03:00
committed by GitHub
3 changed files with 331 additions and 10 deletions

View File

@@ -645,7 +645,7 @@ const isLinkOutputNodeIdOneOf = R.curry((terminalNodeIds, link) =>
// :: [NodeId] -> [Link] -> [[NodeId], [Link]]
const traverseUpAndCollectTerminalChain = R.curry(
(terminalNodeIds, links, collected) => {
const curLink = R.compose(R.last, R.last)(collected);
const curLink = R.last(collected[1]);
if (isLinkOutputNodeIdOneOf(terminalNodeIds, curLink)) {
// collect nodeId + next link & run recursion
@@ -654,8 +654,10 @@ const traverseUpAndCollectTerminalChain = R.curry(
R.compose(R.equals(nextNodeId), Link.getLinkInputNodeId),
links
);
// If the uppermost node has no input link — return collected data
if (!nextLink) return collected;
// If the upper terminal node has no input link — return tuple of empty lists
// to avoid removing this chain of terminals, because it will be done in the
// further step with passing bound values
if (!nextLink) return [[], []];
return R.compose(
traverseUpAndCollectTerminalChain(terminalNodeIds, links),
@@ -683,16 +685,26 @@ const replaceGenericTerminalsWithCastNodes = R.curry(
const linksConnectedToTerminals = R.filter(
R.compose(
linkNodeIds => R.any(R.contains(R.__, linkNodeIds), terminalNodeIds),
linkNodeIds => R.any(isAmong(linkNodeIds), terminalNodeIds),
Link.getLinkNodeIds
),
links
);
const lowermostTerminalLinks = R.filter(
R.compose(
R.complement(R.contains)(R.__, terminalNodeIds),
Link.getLinkInputNodeId
R.either(
// link inputs into non terminal node
R.compose(
R.complement(isAmong(terminalNodeIds)),
Link.getLinkInputNodeId
),
// or into terminal node, which not have a links below
R.compose(
R.not,
R.find(R.__, links),
Link.isLinkOutputNodeIdEquals,
Link.getLinkInputNodeId
)
),
linksConnectedToTerminals
);
@@ -742,14 +754,13 @@ const replaceGenericTerminalsWithCastNodes = R.curry(
)(terminalChains);
const nodesWithoutTerminals = R.reject(
R.compose(R.contains(R.__, nodeIdsToOmit), Node.getNodeId),
R.compose(isAmong(nodeIdsToOmit), Node.getNodeId),
nodes
);
const linksWithoutTerminalLinks = R.reject(
R.compose(R.contains(R.__, linkIdsToOmit), Link.getLinkId),
R.compose(isAmong(linkIdsToOmit), Link.getLinkId),
links
);
const newNodesAndLinks = R.map(
splitLinkWithCastNode(project, patchTuples, nodesWithoutTerminals),
directLinks

View File

@@ -665,6 +665,261 @@
}
},
"path": "xod/i2c/test"
},
"@/test-unlinked-lowermost-terminal": {
"links": {
"original1": {
"id": "original1",
"input": {
"nodeId": "testNode",
"pinKey": "input-color"
},
"output": {
"nodeId": "colorHslNode",
"pinKey": "output-color"
}
},
"toWatch": {
"id": "toWatch",
"input": {
"nodeId": "watch-node",
"pinKey": "input-string"
},
"output": {
"nodeId": "testNode",
"pinKey": "output-string"
}
}
},
"nodes": {
"testNode": {
"id": "testNode",
"position": {
"x": -8,
"y": -1,
"units": "slots"
},
"type": "@/unlinked-custom-terminal"
},
"colorHslNode": {
"id": "colorHslNode",
"position": {
"x": -8,
"y": -2,
"units": "slots"
},
"type": "xod/color/color-hsl"
},
"watch-node": {
"id": "watch-node",
"position": {
"x": -8,
"y": 1,
"units": "slots"
},
"type": "xod/debug/watch"
}
},
"path": "@/test-unlinked-lowermost-terminal"
},
"@/unlinked-custom-terminal": {
"links": {
"toFormatColor": {
"id": "toFormatColor",
"input": {
"nodeId": "formatColorNode",
"pinKey": "input-color"
},
"output": {
"nodeId": "input-color",
"pinKey": "__out__"
}
},
"toOutputString": {
"id": "toOutputString",
"input": {
"nodeId": "output-string",
"pinKey": "__in__"
},
"output": {
"nodeId": "formatColorNode",
"pinKey": "output-string"
}
},
"toOutputColor": {
"id": "toOutputColor",
"input": {
"nodeId": "output-color",
"pinKey": "__in__"
},
"output": {
"nodeId": "input-color",
"pinKey": "__out__"
}
}
},
"nodes": {
"output-color": {
"id": "output-color",
"position": {
"x": 0,
"y": 2,
"units": "slots"
},
"type": "xod/color/output-color"
},
"formatColorNode": {
"id": "formatColorNode",
"position": {
"x": 2,
"y": 1,
"units": "slots"
},
"type": "xod/color/format-color"
},
"input-color": {
"id": "input-color",
"position": {
"x": 0,
"y": 0,
"units": "slots"
},
"type": "xod/color/input-color"
},
"output-string": {
"id": "output-string",
"position": {
"x": 2,
"y": 2,
"units": "slots"
},
"type": "xod/patch-nodes/output-string"
}
},
"path": "@/unlinked-custom-terminal"
},
"@/test-nested-input-color": {
"nodes": {
"nested-format-color": {
"boundLiterals": {
"input-color-1": "#0000FF",
"input-color-2": "#FF0000"
},
"id": "nested-format-color",
"position": {
"x": -5,
"y": -1,
"units": "slots"
},
"type": "@/nested-format-color"
}
},
"path": "@/test-nested-input-color"
},
"@/nested-format-color": {
"links": {
"ByAbAISQv": {
"id": "ByAbAISQv",
"input": {
"nodeId": "format-color-1",
"pinKey": "input-color"
},
"output": {
"nodeId": "input-color-1",
"pinKey": "__out__"
}
},
"H1MG0IBQv": {
"id": "H1MG0IBQv",
"input": {
"nodeId": "output-string-1",
"pinKey": "__in__"
},
"output": {
"nodeId": "format-color-2",
"pinKey": "output-string"
}
},
"SJLMAIH7w": {
"id": "SJLMAIH7w",
"input": {
"nodeId": "output-string-2",
"pinKey": "__in__"
},
"output": {
"nodeId": "format-color-1",
"pinKey": "output-string"
}
},
"SJqbR8BQw": {
"id": "SJqbR8BQw",
"input": {
"nodeId": "format-color-2",
"pinKey": "input-color"
},
"output": {
"nodeId": "input-color-2",
"pinKey": "__out__"
}
}
},
"nodes": {
"input-color-1": {
"id": "input-color-1",
"position": {
"x": 3,
"y": 0,
"units": "slots"
},
"type": "xod/color/input-color"
},
"format-color-1": {
"id": "format-color-1",
"position": {
"x": 3,
"y": 1,
"units": "slots"
},
"type": "xod/color/format-color"
},
"output-string-1": {
"id": "output-string-1",
"position": {
"x": 1,
"y": 2,
"units": "slots"
},
"type": "xod/patch-nodes/output-string"
},
"input-color-2": {
"id": "input-color-2",
"position": {
"x": 1,
"y": 0,
"units": "slots"
},
"type": "xod/color/input-color"
},
"output-string-2": {
"id": "output-string-2",
"position": {
"x": 3,
"y": 2,
"units": "slots"
},
"type": "xod/patch-nodes/output-string"
},
"format-color-2": {
"id": "format-color-2",
"position": {
"x": 1,
"y": 1,
"units": "slots"
},
"type": "xod/color/format-color"
}
},
"path": "@/nested-format-color"
}
}
}

View File

@@ -7,6 +7,7 @@ import * as Helper from './helpers';
import * as Project from '../src/project';
import * as Patch from '../src/patch';
import * as Node from '../src/node';
import * as Link from '../src/link';
import * as Attachment from '../src/attachment';
import * as CONST from '../src/constants';
import flatten, { extractPatches, extractLeafPatches } from '../src/flatten';
@@ -1378,6 +1379,60 @@ describe('Flatten', () => {
}, flatProject);
});
it('should get rid of output terminals without output links', () => {
const flatProject = flatten(
project,
'@/test-unlinked-lowermost-terminal'
);
Helper.expectEitherRight(newProject => {
const nodeIds = R.compose(
R.map(Node.getNodeId),
Patch.listNodes,
Project.getPatchByPathUnsafe('@/test-unlinked-lowermost-terminal')
)(newProject);
const linkIds = R.compose(
R.map(Link.getLinkId),
Patch.listLinks,
Project.getPatchByPathUnsafe('@/test-unlinked-lowermost-terminal')
)(newProject);
assert.sameMembers(
['testNode~formatColorNode', 'colorHslNode', 'watch-node'],
nodeIds
);
assert.sameMembers(
['toWatch', 'original1-to-testNode~toFormatColor'],
linkIds
);
}, flatProject);
});
it('should pass bound values to nested castable custom type terminals', () => {
const flatProject = flatten(project, '@/test-nested-input-color');
Helper.expectEitherRight(newProject => {
const nodeIds = R.compose(
R.map(Node.getNodeId),
Patch.listNodes,
Project.getPatchByPathUnsafe('@/test-nested-input-color')
)(newProject);
const links = R.compose(
Patch.listLinks,
Project.getPatchByPathUnsafe('@/test-nested-input-color')
)(newProject);
assert.sameMembers(
[
'nested-format-color~format-color-1',
'nested-format-color~format-color-2',
],
nodeIds
);
assert.isEmpty(links);
}, flatProject);
});
it('should return Either.Left if custom type does not have a cast node', () => {
const flatProject = flatten(project, '@/test-no-cast-node');
Helper.expectEitherError(