Skip to content

Conversation

@tstirrat15
Copy link
Collaborator

@tstirrat15 tstirrat15 commented Dec 4, 2025

Description

Part of getting composable schema support into vscode.

Note

I haven't yet been able to test this against the extension because we need to update some part of SpiceDB (likely the LSP, but need to figure that out) before it's possible to test this. I'm pretty sure this code works, based on the tests and types, and I figure we can do the integration work when we get there.

Changes

Will annotate.

Testing

Review. Hide whitespace for a nicer diff, especially in the test file. See that tests pass.

@tstirrat15 tstirrat15 force-pushed the add-partial-parsing branch 2 times, most recently from 613af9b to cf4a8c6 Compare December 4, 2025 23:20
@tstirrat15 tstirrat15 changed the title Add partial parsing Add parsing of partials and imports Dec 5, 2025
@tstirrat15 tstirrat15 force-pushed the add-partial-parsing branch 3 times, most recently from 9c959e2 to 2650f8f Compare December 5, 2025 18:14
Copy link
Collaborator Author

@tstirrat15 tstirrat15 left a comment

Choose a reason for hiding this comment

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

See comments.

Comment on lines -4 to -10
ParsedBinaryExpression,
ParsedCaveatDefinition,
ParsedNamedArrowExpression,
ParsedNilExpression,
ParsedObjectDefinition,
ParsedRelationRefExpression,
ParsedUseFlag,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I got rid of all of the casts in this file, so the types are no longer necessary.

const schema = `use expiration`;
const parsed = parseSchema(schema);

expect(parsed?.definitions).toHaveLength(1);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I changed most of the .length).toEqual()s to .toHaveLength()s - it's a better assertion for the context.

Comment on lines +26 to +27
assert(useFlag);
assert(useFlag.kind === "use");
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The use of assert here is what means that we don't need the ases anymore. It does the narrowing for us.


describe("imports", () => {
it("parses basic import", () => {
const schema = `import "foo/bar/baz.zed"`;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here's the tests for import syntax. Lemme know if there's other tests you'd want to see.

});
});

describe("partial syntax", () => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Partial tests are here. Lemme know if there are others you want to see.

},
);
});
const caveatParameterTypeExpr: Parser<ParsedCaveatParameterTypeRef> = lazy(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The only thing that changed here is the type on the parser, but prettier reordered things so it looks like more changed.

Comment on lines +872 to +875
.or(partial)
.or(caveat)
.or(useFlag)
.or(importExpression);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We added both partial and importExpression here as potential toplevels.

Comment on lines +955 to +959
const mapParseNodes =
(mapper: (node: ParsedNode) => void) => (node: ParsedNode | undefined) => {
if (node === undefined) {
return;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I left the contents of this mostly unchanged, but I changed the signature from being a function that takes a node and a mapper to a function that takes a mapper and returns a function that takes a node. This made the recursive calls a little nicer.

I'm not entirely sure that the mapper even really needs to be in there in the way it is; I may update that further later.

Comment on lines +969 to +972
case "partial":
node.relations.forEach(mapParseNodes(mapper));
node.permissions.forEach(mapParseNodes(mapper));
break;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We added this case to the switch.


switch (node.kind) {
case "objectDef":
node.relations.forEach(mapParseNodes(mapper));
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is the part that got a little nicer - mapParseNodes(mapper) can be handed directly to forEach.

@tstirrat15 tstirrat15 marked this pull request as ready for review December 5, 2025 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants