package org.zwobble.hobgoblin.compiler.parser; import org.junit.jupiter.api.Test; import org.zwobble.hobgoblin.compiler.ast.DocComment; import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode; import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode; import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelReferenceNode; import static org.zwobble.hobgoblin.compiler.parser.ParserTesting.parseString; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.*; public class ParserStructDefinitionTests { @Test public void emptyStruct() { var source = """ struct Point { }"""; var node = parseString( source, Parser::parseNamespaceStatement ); assertThat(node, instanceOf( UntypedStructDefinitionNode.class, has("name", UntypedStructDefinitionNode::name, equalTo("Point")), has("fields", UntypedStructDefinitionNode::fields, isOptionalOf(isSequence())) )); } @Test public void structWithFields() { var source = """ struct Point { field x: Int; field y: Int; }"""; var node = parseString( source, Parser::parseNamespaceStatement ); assertThat(node, instanceOf( UntypedStructDefinitionNode.class, has("fields", UntypedStructDefinitionNode::fields, isOptionalOf(isSequence( instanceOf( UntypedStructFieldDefinitionNode.class, has("name", UntypedStructFieldDefinitionNode::name, equalTo("x")), has( "type", UntypedStructFieldDefinitionNode::type, instanceOf( UntypedTypeLevelReferenceNode.class, has("name", UntypedTypeLevelReferenceNode::name, equalTo("Int")) ) ) ), instanceOf( UntypedStructFieldDefinitionNode.class, has("name", UntypedStructFieldDefinitionNode::name, equalTo("y")), has( "type", UntypedStructFieldDefinitionNode::type, instanceOf( UntypedTypeLevelReferenceNode.class, has("name", UntypedTypeLevelReferenceNode::name, equalTo("Int")) ) ) ) ))) )); } @Test public void singletonStruct() { var source = """ struct Point { singleton; }"""; var node = parseString( source, Parser::parseNamespaceStatement ); assertThat(node, instanceOf( UntypedStructDefinitionNode.class, has("fields", UntypedStructDefinitionNode::fields, isOptionalEmpty()) )); } @Test public void structWithDocComment() { var source = """ /// A 2D point. /// /// Positive y is up. struct Point { }"""; var node = parseString( source, Parser::parseNamespaceStatement ); assertThat(node, instanceOf( UntypedStructDefinitionNode.class, has( "docComment", UntypedStructDefinitionNode::docComment, equalTo(new DocComment("A 2D point.\n\nPositive y is up.\n")) ) )); } }