diff --git a/pkg/composableschemadsl/dslshape/dslshape.go b/pkg/composableschemadsl/dslshape/dslshape.go index 1d5a480165..4537224080 100644 --- a/pkg/composableschemadsl/dslshape/dslshape.go +++ b/pkg/composableschemadsl/dslshape/dslshape.go @@ -198,4 +198,5 @@ const ( NodeImportPredicateSource = "import-source" NodeImportPredicatePathSegment = "path-segment" NodeImportPredicateDefinitionName = "imported-definition" + NodeImportPredicateImportAll = "import-all-definitions" ) diff --git a/pkg/composableschemadsl/parser/parser.go b/pkg/composableschemadsl/parser/parser.go index 3fa95d402b..e486833a3c 100644 --- a/pkg/composableschemadsl/parser/parser.go +++ b/pkg/composableschemadsl/parser/parser.go @@ -645,7 +645,13 @@ func (p *sourceParser) consumeImport() AstNode { return importNode } - // Consume alternating identifiers and commas until we reach the end of the import statement + // Look for a * to indicate "import all" + if _, ok := p.tryConsume(lexer.TokenTypeStar); ok { + importNode.MustDecorateWithInt(dslshape.NodeImportPredicateImportAll, 1) + return importNode + } + + // Else consume alternating identifiers and commas until we reach the end of the import statement for { definitionNode, ok := p.consumeIdentifierLiteral() // We connect the node so that the error information is retained, then break the loop diff --git a/pkg/composableschemadsl/parser/parser_test.go b/pkg/composableschemadsl/parser/parser_test.go index 066e95408c..3353ac7cd4 100644 --- a/pkg/composableschemadsl/parser/parser_test.go +++ b/pkg/composableschemadsl/parser/parser_test.go @@ -129,6 +129,9 @@ func TestParser(t *testing.T) { {"local imports with malformed import path test", "localimport_malformed_import_path"}, {"local imports with path missing leading period test", "localimport_path_missing_leading_period"}, {"local imports with typo in import separator test", "localimport_typo_in_import_separator"}, + {"local imports with import all asterisk", "localimport_with_import_all"}, + {"local imports with import all asterisk and import identifiers", "localimport_with_import_all_and_imports"}, + {"local imports with import identifiers and import all asterisk", "localimport_with_imports_and_import_all"}, } for _, test := range parserTests { diff --git a/pkg/composableschemadsl/parser/tests/localimport_with_import_all.zed b/pkg/composableschemadsl/parser/tests/localimport_with_import_all.zed new file mode 100644 index 0000000000..0d15a224e1 --- /dev/null +++ b/pkg/composableschemadsl/parser/tests/localimport_with_import_all.zed @@ -0,0 +1,7 @@ +from .path.to.user import * + +definition resource { + relation user: user + relation persona: persona + permission view = user + persona +} diff --git a/pkg/composableschemadsl/parser/tests/localimport_with_import_all.zed.expected b/pkg/composableschemadsl/parser/tests/localimport_with_import_all.zed.expected new file mode 100644 index 0000000000..13fff4d242 --- /dev/null +++ b/pkg/composableschemadsl/parser/tests/localimport_with_import_all.zed.expected @@ -0,0 +1,86 @@ +NodeTypeFile + end-rune = 143 + input-source = local imports with import all asterisk + start-rune = 0 + child-node => + NodeTypeImport + end-rune = 26 + import-all-definitions = 1 + input-source = local imports with import all asterisk + start-rune = 0 + path-segment => + NodeTypeIdentifier + end-rune = 9 + identifier-value = path + input-source = local imports with import all asterisk + start-rune = 6 + NodeTypeIdentifier + end-rune = 12 + identifier-value = to + input-source = local imports with import all asterisk + start-rune = 11 + NodeTypeIdentifier + end-rune = 17 + identifier-value = user + input-source = local imports with import all asterisk + start-rune = 14 + NodeTypeDefinition + definition-name = resource + end-rune = 142 + input-source = local imports with import all asterisk + start-rune = 29 + child-node => + NodeTypeRelation + end-rune = 73 + input-source = local imports with import all asterisk + relation-name = user + start-rune = 55 + allowed-types => + NodeTypeTypeReference + end-rune = 73 + input-source = local imports with import all asterisk + start-rune = 70 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 73 + input-source = local imports with import all asterisk + start-rune = 70 + type-name = user + NodeTypeRelation + end-rune = 103 + input-source = local imports with import all asterisk + relation-name = persona + start-rune = 79 + allowed-types => + NodeTypeTypeReference + end-rune = 103 + input-source = local imports with import all asterisk + start-rune = 97 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 103 + input-source = local imports with import all asterisk + start-rune = 97 + type-name = persona + NodeTypePermission + end-rune = 140 + input-source = local imports with import all asterisk + relation-name = view + start-rune = 109 + compute-expression => + NodeTypeUnionExpression + end-rune = 140 + input-source = local imports with import all asterisk + start-rune = 127 + left-expr => + NodeTypeIdentifier + end-rune = 130 + identifier-value = user + input-source = local imports with import all asterisk + start-rune = 127 + right-expr => + NodeTypeIdentifier + end-rune = 140 + identifier-value = persona + input-source = local imports with import all asterisk + start-rune = 134 \ No newline at end of file diff --git a/pkg/composableschemadsl/parser/tests/localimport_with_import_all_and_imports.zed b/pkg/composableschemadsl/parser/tests/localimport_with_import_all_and_imports.zed new file mode 100644 index 0000000000..39d93bcbc8 --- /dev/null +++ b/pkg/composableschemadsl/parser/tests/localimport_with_import_all_and_imports.zed @@ -0,0 +1,7 @@ +from .path.to.user import *, user, persona + +definition resource { + relation user: user + relation persona: persona + permission view = user + persona +} diff --git a/pkg/composableschemadsl/parser/tests/localimport_with_import_all_and_imports.zed.expected b/pkg/composableschemadsl/parser/tests/localimport_with_import_all_and_imports.zed.expected new file mode 100644 index 0000000000..6111ba7eb4 --- /dev/null +++ b/pkg/composableschemadsl/parser/tests/localimport_with_import_all_and_imports.zed.expected @@ -0,0 +1,32 @@ +NodeTypeFile + end-rune = 26 + input-source = local imports with import all asterisk and import identifiers + start-rune = 0 + child-node => + NodeTypeImport + end-rune = 26 + import-all-definitions = 1 + input-source = local imports with import all asterisk and import identifiers + start-rune = 0 + path-segment => + NodeTypeIdentifier + end-rune = 9 + identifier-value = path + input-source = local imports with import all asterisk and import identifiers + start-rune = 6 + NodeTypeIdentifier + end-rune = 12 + identifier-value = to + input-source = local imports with import all asterisk and import identifiers + start-rune = 11 + NodeTypeIdentifier + end-rune = 17 + identifier-value = user + input-source = local imports with import all asterisk and import identifiers + start-rune = 14 + NodeTypeError + end-rune = 26 + error-message = Unexpected token at root level: TokenTypeComma + error-source = , + input-source = local imports with import all asterisk and import identifiers + start-rune = 27 \ No newline at end of file diff --git a/pkg/composableschemadsl/parser/tests/localimport_with_imports_and_import_all.zed b/pkg/composableschemadsl/parser/tests/localimport_with_imports_and_import_all.zed new file mode 100644 index 0000000000..3417082983 --- /dev/null +++ b/pkg/composableschemadsl/parser/tests/localimport_with_imports_and_import_all.zed @@ -0,0 +1,7 @@ +from .path.to.user import user, persona, * + +definition resource { + relation user: user + relation persona: persona + permission view = user + persona +} diff --git a/pkg/composableschemadsl/parser/tests/localimport_with_imports_and_import_all.zed.expected b/pkg/composableschemadsl/parser/tests/localimport_with_imports_and_import_all.zed.expected new file mode 100644 index 0000000000..0eb2a5d008 --- /dev/null +++ b/pkg/composableschemadsl/parser/tests/localimport_with_imports_and_import_all.zed.expected @@ -0,0 +1,53 @@ +NodeTypeFile + end-rune = 39 + input-source = local imports with import identifiers and import all asterisk + start-rune = 0 + child-node => + NodeTypeImport + end-rune = 39 + input-source = local imports with import identifiers and import all asterisk + start-rune = 0 + imported-definition => + NodeTypeIdentifier + end-rune = 29 + identifier-value = user + input-source = local imports with import identifiers and import all asterisk + start-rune = 26 + NodeTypeIdentifier + end-rune = 38 + identifier-value = persona + input-source = local imports with import identifiers and import all asterisk + start-rune = 32 + NodeTypeIdentifier + end-rune = 39 + input-source = local imports with import identifiers and import all asterisk + start-rune = 41 + child-node => + NodeTypeError + end-rune = 39 + error-message = Expected identifier, found token TokenTypeStar + error-source = * + input-source = local imports with import identifiers and import all asterisk + start-rune = 41 + path-segment => + NodeTypeIdentifier + end-rune = 9 + identifier-value = path + input-source = local imports with import identifiers and import all asterisk + start-rune = 6 + NodeTypeIdentifier + end-rune = 12 + identifier-value = to + input-source = local imports with import identifiers and import all asterisk + start-rune = 11 + NodeTypeIdentifier + end-rune = 17 + identifier-value = user + input-source = local imports with import identifiers and import all asterisk + start-rune = 14 + NodeTypeError + end-rune = 39 + error-message = Unexpected token at root level: TokenTypeStar + error-source = * + input-source = local imports with import identifiers and import all asterisk + start-rune = 41 \ No newline at end of file