From 48f686951979f8fa8bd3b424a5139dd9150efec6 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 28 Sep 2023 10:48:27 +0100 Subject: Add struct type to context --- .../compiler/ast/typed/TypedNodeMatchers.java | 11 ++- .../typechecker/TypeCheckerAssignTests.java | 19 +++--- .../typechecker/TypeCheckerContextTests.java | 13 ++-- .../TypeCheckerFunctionDefinitionTests.java | 7 +- .../TypeCheckerFunctionReturnTests.java | 3 +- .../compiler/typechecker/TypeCheckerIfTests.java | 3 +- .../typechecker/TypeCheckerNamespaceTests.java | 78 ++++++++++++++++++++++ .../TypeCheckerStructDefinitionTests.java | 26 +++++++- .../compiler/typechecker/TypeCheckerValTests.java | 5 +- .../compiler/typechecker/TypeCheckerVarTests.java | 5 +- .../org/shedlang/compiler/types/TypeMatchers.java | 18 +++++ 11 files changed, 158 insertions(+), 30 deletions(-) create mode 100644 src/test/java/org/shedlang/compiler/types/TypeMatchers.java (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java index 82221c08..e5b13e6c 100644 --- a/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java +++ b/src/test/java/org/shedlang/compiler/ast/typed/TypedNodeMatchers.java @@ -283,15 +283,22 @@ public class TypedNodeMatchers { public static Matcher> isTypedTypeLevelReferenceNode( String name, - TypeLevelValue value + Matcher value ) { return instanceOf( TypedTypeLevelReferenceNode.class, has("name", x -> x.name(), equalTo(name)), - has("value", x -> x.value(), equalTo(value)) + has("value", x -> x.value(), value) ); } + public static Matcher> isTypedTypeLevelReferenceNode( + String name, + TypeLevelValue value + ) { + return isTypedTypeLevelReferenceNode(name, equalTo(value)); + } + public static Matcher isTypedValNode( String targetName, Matcher expression diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java index 9bd07ffd..cc161b56 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerAssignTests.java @@ -10,6 +10,7 @@ import org.shedlang.compiler.typechecker.errors.CanOnlyAssignToVarError; import org.shedlang.compiler.typechecker.errors.TargetTupleHasWrongElementCount; import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; import org.shedlang.compiler.typechecker.typesets.TypeSets; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.TupleType; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -27,7 +28,7 @@ public class TypeCheckerAssignTests { public void canTypeCheckTargetIgnore() { var untyped = Untyped.assign(Untyped.targetIgnore(), Untyped.stringLiteral("hello")); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.STRING, VariableType.VAR)) )); @@ -43,7 +44,7 @@ public class TypeCheckerAssignTests { public void canTypeCheckReassign() { var untyped = Untyped.assign(Untyped.targetReassign("x"), Untyped.stringLiteral("hello")); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.STRING, VariableType.VAR)) )); @@ -59,7 +60,7 @@ public class TypeCheckerAssignTests { public void whenExpressionIsNotSubTypeOfReassignTargetVariableThenErrorIsThrown() { var untyped = Untyped.assign(Untyped.targetReassign("x"), Untyped.stringLiteral("hello")); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.INT, VariableType.VAR)) )); @@ -76,7 +77,7 @@ public class TypeCheckerAssignTests { public void whenReassignTargetIsNotVarThenErrorIsThrown() { var untyped = Untyped.assign(Untyped.targetReassign("x"), Untyped.stringLiteral("hello")); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.STRING, VariableType.VAL)) )); @@ -102,7 +103,7 @@ public class TypeCheckerAssignTests { Types.BOOL )); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(tupleType, VariableType.VAL)) )); @@ -128,7 +129,7 @@ public class TypeCheckerAssignTests { Untyped.reference("x") ); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.INT, VariableType.VAL)) )); @@ -152,7 +153,7 @@ public class TypeCheckerAssignTests { ); var tupleType = new TupleType(List.of(Types.STRING)); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(tupleType, VariableType.VAL)) )); @@ -172,7 +173,7 @@ public class TypeCheckerAssignTests { var declaredVariables = DeclaredVariables.forFunctionStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckFunctionStatement(untyped, context); } @@ -184,7 +185,7 @@ public class TypeCheckerAssignTests { var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java index c3791df8..aa06e499 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerContextTests.java @@ -5,6 +5,7 @@ import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.typechecker.errors.CannotDefineVariableDeclaredInOuterScopeError; import org.shedlang.compiler.typechecker.errors.UnknownVariableError; import org.shedlang.compiler.typechecker.errors.VariableIsAlreadyDefinedError; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -18,7 +19,7 @@ public class TypeCheckerContextTests { @Test public void givenVariableIsUndefinedWhenVariableIsDefinedThenVariableHasTypeSet() { var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.undefined(VariableType.VAL)), Map.entry("y", Variable.undefined(VariableType.VAL)) )); @@ -32,7 +33,7 @@ public class TypeCheckerContextTests { @Test public void givenVariableIsUnknownWhenVariableIsDefinedThenErrorIsThrown() { var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("y", Variable.undefined(VariableType.VAL)) )); @@ -47,7 +48,7 @@ public class TypeCheckerContextTests { @Test public void givenVariableIsDefinedWhenVariableIsDefinedThenErrorIsThrown() { var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.STRING, VariableType.VAL)) )); @@ -62,10 +63,10 @@ public class TypeCheckerContextTests { @Test public void givenVariableIsBoundInOuterScopeWhenVariableIsDefinedThenErrorIsThrown() { var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.undefined(VariableType.VAL)) )) - .enterNamespace(P.map()); + .enterNamespace(NamespaceName.of("Example"), P.map()); var error = assertThrows( CannotDefineVariableDeclaredInOuterScopeError.class, @@ -78,7 +79,7 @@ public class TypeCheckerContextTests { @Test public void definingVariableOnlyAffectsTopMostLexicalContext() { var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.undefined(VariableType.VAL)), Map.entry("y", Variable.undefined(VariableType.VAL)) )); diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java index 136dce36..d6a600bc 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionDefinitionTests.java @@ -7,10 +7,7 @@ import org.shedlang.compiler.ast.untyped.UntypedCallNode; import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode; import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; import org.shedlang.compiler.typechecker.typesets.TypeSets; -import org.shedlang.compiler.types.Effects; -import org.shedlang.compiler.types.FunctionType; -import org.shedlang.compiler.types.NamedParam; -import org.shedlang.compiler.types.Types; +import org.shedlang.compiler.types.*; import org.shedlang.compiler.util.P; import java.util.List; @@ -394,7 +391,7 @@ public class TypeCheckerFunctionDefinitionTests { var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java index 2e4b4206..2a8ae446 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerFunctionReturnTests.java @@ -6,6 +6,7 @@ import org.shedlang.compiler.typechecker.errors.CannotReturnOutsideOfFunction; import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; import org.shedlang.compiler.typechecker.typesets.TypeSets; import org.shedlang.compiler.types.Effects; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -30,7 +31,7 @@ public class TypeCheckerFunctionReturnTests { public void whenNotInFunctionThenReturnIsForbidden() { var untyped = Untyped.functionReturn(Untyped.stringLiteral("hello")); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map()); + .enterNamespace(NamespaceName.of("Example"), P.map()); assertThrows( CannotReturnOutsideOfFunction.class, diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIfTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIfTests.java index adb5968c..c619409b 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIfTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIfTests.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.typechecker.errors.UnexpectedTypeError; import org.shedlang.compiler.typechecker.typesets.TypeSets; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -128,7 +129,7 @@ public class TypeCheckerIfTests { )) ); var context = TypeCheckerContext.EMPTY - .enterNamespace(P.map( + .enterNamespace(NamespaceName.of("Example"), P.map( Map.entry("x", Variable.defined(Types.STRING, VariableType.VAL)) )); diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNamespaceTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNamespaceTests.java index 36e1ee5d..d8fdc3ee 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNamespaceTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerNamespaceTests.java @@ -3,6 +3,7 @@ package org.shedlang.compiler.typechecker; import org.junit.jupiter.api.Test; import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode; +import org.shedlang.compiler.ast.untyped.UntypedStructDefinitionNode; import org.shedlang.compiler.typechecker.errors.ReferenceBeforeDefinitionError; import org.shedlang.compiler.types.*; import org.shedlang.compiler.util.P; @@ -12,6 +13,7 @@ import java.util.Map; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*; +import static org.shedlang.compiler.types.TypeMatchers.isStructType; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.*; @@ -283,6 +285,82 @@ public class TypeCheckerNamespaceTests { assertThat(error.variableName(), equalTo("y")); } + @Test + public void functionCanUseTypeDefinedEarlier() { + var untyped = Untyped.namespace(NamespaceName.of("Example", "Project"), List.of( + UntypedStructDefinitionNode.builder() + .withName("User") + .build(), + UntypedFunctionDefinitionNode.builder() + .withName("printUser") + .addPositionalParam("user", Untyped.typeLevelReference("User")) + .withReturnType(Untyped.typeLevelReference("Unit")) + .build() + )); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map(Map.entry("Unit", Types.metaType(Types.UNIT)))); + + var result = TypeChecker.typeCheckNamespace(untyped, context); + + assertThat( + result.value(), + isTypedNamespaceNode() + .withBody(isSequence( + isTypedStructDefinitionNode().withName("User"), + isTypedFunctionDefinitionNode() + .withName("printUser") + .withParams(isTypedParamsNode( + isSequence(isTypedParamNode( + "user", + isTypedTypeLevelReferenceNode( + "User", + isStructType(NamespaceName.of("Example", "Project"), "User") + ) + )), + isSequence() + )) + )) + ); + } + + @Test + public void functionCanUseTypeDefinedLater() { + var untyped = Untyped.namespace(NamespaceName.of("Example", "Project"), List.of( + UntypedFunctionDefinitionNode.builder() + .withName("printUser") + .addPositionalParam("user", Untyped.typeLevelReference("User")) + .withReturnType(Untyped.typeLevelReference("Unit")) + .build(), + UntypedStructDefinitionNode.builder() + .withName("User") + .build() + )); + var context = TypeCheckerContext.EMPTY + .enterGlobal(P.map(Map.entry("Unit", Types.metaType(Types.UNIT)))); + + var result = TypeChecker.typeCheckNamespace(untyped, context); + + assertThat( + result.value(), + isTypedNamespaceNode() + .withBody(isSequence( + isTypedFunctionDefinitionNode() + .withName("printUser") + .withParams(isTypedParamsNode( + isSequence(isTypedParamNode( + "user", + isTypedTypeLevelReferenceNode( + "User", + isStructType(NamespaceName.of("Example", "Project"), "User") + ) + )), + isSequence() + )), + isTypedStructDefinitionNode().withName("User") + )) + ); + } + @Test public void typesOfFieldsAreStored() { var namespaceName = NamespaceName.of("Example"); diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java index c8bfd742..dc23fa1c 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerStructDefinitionTests.java @@ -5,6 +5,8 @@ import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode; import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.ast.untyped.UntypedNamespaceStatementNode; import org.shedlang.compiler.ast.untyped.UntypedStructDefinitionNode; +import org.shedlang.compiler.types.NamespaceName; +import org.shedlang.compiler.types.StructType; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -12,9 +14,11 @@ import java.util.Map; import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*; import static org.zwobble.precisely.AssertThat.assertThat; -import static org.zwobble.precisely.Matchers.isSequence; +import static org.zwobble.precisely.Matchers.*; public class TypeCheckerStructDefinitionTests { + private static final NamespaceName NAMESPACE_NAME = NamespaceName.of("Example"); + @Test public void canTypeCheckStructDefinitionWithNoFields() { var untyped = UntypedStructDefinitionNode.builder() @@ -32,6 +36,24 @@ public class TypeCheckerStructDefinitionTests { ); } + @Test + public void typeIsAddedToEnvironment() { + var untyped = UntypedStructDefinitionNode.builder() + .withName("ExampleStruct") + .build(); + var context = TypeCheckerContext.EMPTY; + + var typed = typeCheckNamespaceStatement(untyped, context); + + assertThat( + typed.context().compileTimeLookup("ExampleStruct"), + isOptionalOf(equalTo(Variable.defined( + Types.metaType(Types.struct(NAMESPACE_NAME, "ExampleStruct")), + VariableType.CONSTANT + ))) + ); + } + @Test public void canTypeCheckStructDefinitionWithFields() { var untyped = UntypedStructDefinitionNode.builder() @@ -70,7 +92,7 @@ public class TypeCheckerStructDefinitionTests { var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NAMESPACE_NAME, environment.build()); return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java index 6cb02e1b..9fd948ba 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerValTests.java @@ -6,6 +6,7 @@ import org.shedlang.compiler.ast.typed.TypedNamespaceStatementNode; import org.shedlang.compiler.ast.untyped.*; import org.shedlang.compiler.typechecker.errors.DuplicateVariableName; import org.shedlang.compiler.typechecker.errors.ReferenceBeforeDefinitionError; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -152,7 +153,7 @@ public class TypeCheckerValTests { var declaredVariables = DeclaredVariables.forFunctionStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckFunctionStatement(untyped, context); } @@ -164,7 +165,7 @@ public class TypeCheckerValTests { var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context); } diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java index 21f5502e..466ab16c 100644 --- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java +++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerVarTests.java @@ -7,6 +7,7 @@ import org.shedlang.compiler.ast.untyped.Untyped; import org.shedlang.compiler.ast.untyped.UntypedFunctionDefinitionNode; import org.shedlang.compiler.ast.untyped.UntypedFunctionStatementNode; import org.shedlang.compiler.ast.untyped.UntypedNamespaceStatementNode; +import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.Types; import org.shedlang.compiler.util.P; @@ -60,7 +61,7 @@ public class TypeCheckerVarTests { var declaredVariables = DeclaredVariables.forFunctionStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckFunctionStatement(untyped, context); } @@ -72,7 +73,7 @@ public class TypeCheckerVarTests { var declaredVariables = DeclaredVariables.forNamespaceStatement(untyped, P.vector()); var environment = EnvironmentBuilder.EMPTY.addUndefined(declaredVariables); - context = context.enterNamespace(environment.build()); + context = context.enterNamespace(NamespaceName.of("Example"), environment.build()); return TypeChecker.typeCheckNamespaceStatement(untyped).typeCheckAllPhases(context); } diff --git a/src/test/java/org/shedlang/compiler/types/TypeMatchers.java b/src/test/java/org/shedlang/compiler/types/TypeMatchers.java new file mode 100644 index 00000000..429caec7 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/types/TypeMatchers.java @@ -0,0 +1,18 @@ +package org.shedlang.compiler.types; + +import org.zwobble.precisely.Matcher; + +import static org.zwobble.precisely.Matchers.*; + +public class TypeMatchers { + private TypeMatchers() { + } + + public static Matcher isStructType(NamespaceName namespaceName, String name) { + return instanceOf( + StructType.class, + has("namespaceName", x -> x.namespaceName(), equalTo(namespaceName)), + has("name", x -> x.name(), equalTo(name)) + ); + } +} -- cgit v1.2.3