Skip to content

Commit

Permalink
feat: Show typedefs on canvas (#863)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhess authored Jun 1, 2023
2 parents 889579a + f4b3532 commit 6ad01d9
Show file tree
Hide file tree
Showing 32 changed files with 1,040 additions and 249 deletions.
2 changes: 1 addition & 1 deletion argocd/base/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ spec:
# Note: use the *dev* version of the package here, so that
# PRs can deploy `primer-service` container images that have
# not yet been merged to `primer` `main`.
image: ghcr.io/hackworthltd/primer-service-dev:git-1145eb89eb85354f67ec3cc5e25f59ef092a6c39
image: ghcr.io/hackworthltd/primer-service-dev:git-f35380015a14db87c5f330a84a5830adc51e1cbb
ports:
- containerPort: 8081
env:
Expand Down
8 changes: 4 additions & 4 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Note: don't override any of primer's Nix flake inputs, or else
# we won't hit its binary cache.
primer.url = github:hackworthltd/primer/1145eb89eb85354f67ec3cc5e25f59ef092a6c39;
primer.url = github:hackworthltd/primer/f35380015a14db87c5f330a84a5830adc51e1cbb;

flake-parts.url = "github:hercules-ci/flake-parts";
};
Expand Down
30 changes: 30 additions & 0 deletions src/Actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ export const actionName = (
return prose("r");
case "RenameDef":
return prose("r");
case "RenameType":
return prose("r");
case "AddCon":
return prose("+");
case "RenameCon":
return prose("r");
case "RenameTypeParam":
return prose("r");
case "AddConField":
return prose("+");
}
};

Expand Down Expand Up @@ -171,6 +181,16 @@ export const actionDescription = (
return "Rename this type variable";
case "RenameDef":
return "Rename this definition";
case "RenameType":
return "Rename this type";
case "AddCon":
return "Add a constructor to this type";
case "RenameCon":
return "Rename this constructor";
case "RenameTypeParam":
return "Rename this parameter";
case "AddConField":
return "Add a parameter to this constructor";
}
};

Expand Down Expand Up @@ -246,5 +266,15 @@ export const actionType = (action: NoInputAction | InputAction): ActionType => {
return "Primary";
case "RenameDef":
return "Primary";
case "RenameType":
return "Primary";
case "AddCon":
return "Primary";
case "RenameCon":
return "Primary";
case "RenameTypeParam":
return "Primary";
case "AddConField":
return "Primary";
}
};
30 changes: 9 additions & 21 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,16 @@ const AppNoError = ({
.sort((a, b) => cmpName(a.name, b.name))
.map((d) => d.name.baseName),
types: p.module.types
.sort((a, b) => cmpName(a, b))
.map((t) => t.baseName),
.sort((a, b) => cmpName(a.name, b.name))
.map((t) => t.name.baseName),
importedDefs: p.imports
.flatMap((m) => m.defs)
.sort((a, b) => cmpName(a.name, b.name))
.map((d) => d.name.baseName),
importedTypes: p.imports
.flatMap((m) => m.types)
.sort((a, b) => cmpName(a, b))
.map((t) => t.baseName),
.sort((a, b) => cmpName(a.name, b.name))
.map((t) => t.name.baseName),
}}
onClickDef={(defName, _event) => {
if (scrollToDefRef.current != undefined) {
Expand Down Expand Up @@ -318,23 +318,9 @@ const AppNoError = ({
scrollToDefRef={scrollToDefRef}
{...defaultTreeReactFlowProps}
{...(selection && { selection })}
onNodeClick={(_e, node) => {
if (!("nodeType" in node.data)) {
setSelection({
def: node.data.def,
});
} else {
const id = Number(node.id);
// Non-numeric IDs correspond to non-selectable nodes (those with no ID in backend) e.g. pattern constructors.
if (!isNaN(id)) {
setSelection({
def: node.data.def,
node: { id, nodeType: node.data.nodeType },
});
}
}
}}
onNodeClick={(_e, sel) => sel && setSelection(sel)}
defs={p.module.defs}
typeDefs={p.module.types}
level={level}
/>
</div>
Expand Down Expand Up @@ -394,7 +380,9 @@ const AppNoError = ({
) : null}
{showCreateTypeDefModal ? (
<CreateTypeDefModal
moduleTypeDefNames={new Set(p.module.types.map((t) => t.baseName))}
moduleTypeDefNames={
new Set(p.module.types.map((t) => t.name.baseName))
}
open={showCreateTypeDefModal}
onClose={() => setShowCreateTypeDefModal(false)}
onCancel={() => setShowCreateTypeDefModal(false)}
Expand Down
143 changes: 134 additions & 9 deletions src/components/TreeReactFlow/TreeReactFlow.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
oddEvenTrees,
oddEvenTreesMiscStyles,
} from "@/components/examples/trees";
import { Tree } from "@/primer-api";
import { Tree, TypeDef } from "@/primer-api";

export default {
title: "Application/Component Library/TreeReactFlow",
Expand All @@ -26,7 +26,7 @@ export default {
},
} as ComponentMeta<typeof TreeReactFlow>;

const props: Omit<TreeReactFlowProps, "defs"> = {
const props: Omit<TreeReactFlowProps, "defs" | "typeDefs" | "onNodeClick"> = {
...defaultTreeReactFlowProps,
scrollToDefRef: { current: undefined },
forestLayout: "Vertical",
Expand Down Expand Up @@ -64,6 +64,87 @@ const def5 = {
term: tree5,
type_: emptyTypeTree("5"),
};
const typeDef1: TypeDef = {
name: { qualifiedModule: [], baseName: "Either-ish" },
params: ["a", "b"],
constructors: [
{
name: { qualifiedModule: [], baseName: "Left" },
fields: [
{
nodeId: "1100",
body: {
tag: "TextBody",
contents: {
fst: "TVar",
snd: { baseName: "a" },
},
},
childTrees: [],
},
],
},
{
name: { qualifiedModule: [], baseName: "Right" },
fields: [
{
nodeId: "1101",
body: { tag: "NoBody", contents: "APP" },
childTrees: [
{
nodeId: "1102",
body: { tag: "NoBody", contents: "APP" },
childTrees: [
{
nodeId: "1103",
body: {
tag: "TextBody",
contents: {
fst: "TCon",
snd: { baseName: "Pair" },
},
},
childTrees: [],
},
{
nodeId: "1104",
body: {
tag: "TextBody",
contents: {
fst: "TCon",
snd: { baseName: "Bool" },
},
},
childTrees: [],
},
],
},
{
nodeId: "1105",
body: {
tag: "TextBody",
contents: {
fst: "TVar",
snd: { baseName: "b" },
},
},
childTrees: [],
},
],
},
{
nodeId: "1106",
body: {
tag: "TextBody",
contents: { fst: "TCon", snd: { baseName: "Int" } },
},
childTrees: [],
},
],
},
],
nameHints: ["x", "y"],
};
const oddEvenDefs = oddEvenTrees.map(([baseName, term]) => {
return {
name: { qualifiedModule: [], baseName },
Expand All @@ -90,60 +171,104 @@ export const Tree1: ComponentStory<typeof TreeReactFlow> = (
treeSized({
...args,
defs: [def1],
selection: { def: def1.name, node: { nodeType: "BodyNode", id: 100 } },
typeDefs: [],
selection: {
tag: "SelectionDef",
contents: { def: def1.name, node: { nodeType: "BodyNode", meta: 100 } },
},
});
export const Tree2: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: [def2],
typeDefs: [],
});
export const Tree3: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: [def3],
selection: { def: def3.name, node: { nodeType: "BodyNode", id: 301 } },
typeDefs: [],
selection: {
tag: "SelectionDef",
contents: { def: def3.name, node: { nodeType: "BodyNode", meta: 301 } },
},
});
export const Tree4: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: [def4],
selection: { def: def4.name, node: { nodeType: "BodyNode", id: 409 } },
typeDefs: [],
selection: {
tag: "SelectionDef",
contents: { def: def4.name, node: { nodeType: "BodyNode", meta: 409 } },
},
});
export const Tree5: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: [def5],
selection: { def: def5.name, node: { nodeType: "BodyNode", id: 503 } },
typeDefs: [],
selection: {
tag: "SelectionDef",
contents: { def: def5.name, node: { nodeType: "BodyNode", meta: 503 } },
},
});
export const TreeType1: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: [],
typeDefs: [typeDef1],
selection: {
tag: "SelectionTypeDef",
contents: {
def: typeDef1.name,
node: { tag: "TypeDefParamNodeSelection", contents: "a" },
},
},
});
export const AllTrees: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: [def1, def2, def3, def4, def5],
selection: { def: def3.name, node: { nodeType: "BodyNode", id: 301 } },
typeDefs: [typeDef1],
selection: {
tag: "SelectionDef",
contents: { def: def3.name, node: { nodeType: "BodyNode", meta: 301 } },
},
});
export const OddAndEven: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: oddEvenDefs,
selection: { def: def5.name, node: { nodeType: "BodyNode", id: 5 } },
typeDefs: [],
selection: {
tag: "SelectionDef",
contents: { def: def5.name, node: { nodeType: "BodyNode", meta: 5 } },
},
});
export const OddAndEvenMiscStyles: ComponentStory<typeof TreeReactFlow> = (
args: TreeReactFlowProps
) =>
treeSized({
...args,
defs: oddEvenDefsMiscStyles,
selection: { def: def5.name, node: { nodeType: "BodyNode", id: 5 } },
typeDefs: [],
selection: {
tag: "SelectionDef",
contents: { def: def5.name, node: { nodeType: "BodyNode", meta: 5 } },
},
});
Loading

0 comments on commit 6ad01d9

Please sign in to comment.