From ec991d698738d70449ab77134e3c18d9687fada0 Mon Sep 17 00:00:00 2001 From: Rafael Bey Date: Sat, 23 Nov 2024 12:30:57 -0500 Subject: [PATCH] Protocol fixing when parsing old grammar --- .../grammar/test/TestGrammarRoundtrip.java | 4 + .../roundtrip/TestDomainGrammarRoundtrip.java | 91 +++++++++++++++---- .../v1/model/valueSpecification/Variable.java | 17 +++- .../application/AppliedFunction.java | 68 ++++++++------ 4 files changed, 136 insertions(+), 44 deletions(-) diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java index 3001358cb67..77933497a25 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestGrammarRoundtrip.java @@ -152,6 +152,10 @@ private static void testFormat(String code, String unformattedCode, boolean omit { parsedModel = PureModelContextData.newPureModelContextData(parsedModel.getSerializer(), parsedModel.getOrigin(), LazyIterate.reject(parsedModel.getElements(), e -> e instanceof SectionIndex)); } + + // run json deserializer to apply protocol updates (migrate from old to new)... + parsedModel = ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolExtensionSupports().convertValue(parsedModel, PureModelContextData.class); + String formatted = grammarTransformer.renderPureModelContextData(parsedModel); Assert.assertEquals(code, formatted); // NOTE: do not remove the round-trip test for formatted code as this is a very good way to ensure that grammar <-> >protocol is bijective diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java index 2eef4809fb8..50e008462f3 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-grammar/src/test/java/org/finos/legend/engine/language/pure/grammar/test/roundtrip/TestDomainGrammarRoundtrip.java @@ -512,7 +512,7 @@ public void testInFixFunctionAsParameter() } @Test - public void testNewConstructorWithTypeArgumentsIsBackwardCompatible() throws JsonProcessingException + public void testTypeArgumentsAreBackwardCompatibleForOldProtocolMissingIt() throws JsonProcessingException { testComposedGrammar("{\n" + " \"_type\": \"data\",\n" + @@ -603,21 +603,6 @@ public void testNewConstructorWithTypeArgumentsIsBackwardCompatible() throws Jso " \"stereotypes\": [],\n" + " \"taggedValues\": [],\n" + " \"tests\": []\n" + - " },\n" + - " {\n" + - " \"_type\": \"sectionIndex\",\n" + - " \"name\": \"SectionIndex\",\n" + - " \"package\": \"__internal__\",\n" + - " \"sections\": [\n" + - " {\n" + - " \"_type\": \"importAware\",\n" + - " \"elements\": [\n" + - " \"test::new__Any_1_\"\n" + - " ],\n" + - " \"imports\": [],\n" + - " \"parserName\": \"Pure\"\n" + - " }\n" + - " ]\n" + " }\n" + " ]\n" + "}", @@ -625,6 +610,80 @@ public void testNewConstructorWithTypeArgumentsIsBackwardCompatible() throws Jso "{\n" + " ^BasicColumnSpecification(func=r: TDSRow[1]|1)\n" + "}\n"); + + testComposedGrammar("{\n" + + " \"_type\": \"data\",\n" + + " \"elements\": [\n" + + " {\n" + + " \"_type\": \"function\",\n" + + " \"body\": [\n" + + " {\n" + + " \"_type\": \"integer\",\n" + + " \"value\": 1\n" + + " }\n" + + " ],\n" + + " \"name\": \"new_Result_1__Any_1_\",\n" + + " \"package\": \"test\",\n" + + " \"parameters\": [\n" + + " {\n" + + " \"_type\": \"var\",\n" + + // ---------- old variable type inside class property + " \"class\": \"Result\",\n" + + // ---------- old variable type inside class property + " \"multiplicity\": {\n" + + " \"lowerBound\": 1,\n" + + " \"upperBound\": 1\n" + + " },\n" + + " \"name\": \"res\"\n" + + " }\n" + + " ],\n" + + " \"postConstraints\": [],\n" + + " \"preConstraints\": [],\n" + + " \"returnGenericType\": {\n" + + " \"multiplicityArguments\": [],\n" + + " \"rawType\": {\n" + + " \"_type\": \"packageableType\",\n" + + " \"fullPath\": \"Any\"\n" + + " },\n" + + " \"typeArguments\": [],\n" + + " \"typeVariableValues\": []\n" + + " },\n" + + " \"returnMultiplicity\": {\n" + + " \"lowerBound\": 1,\n" + + " \"upperBound\": 1\n" + + " },\n" + + " \"stereotypes\": [],\n" + + " \"taggedValues\": [],\n" + + " \"tests\": []\n" + + " }\n" + + " ]\n" + + "}", + "function test::new(res: Result[1]): Any[1]\n" + + "{\n" + + " 1\n" + + "}\n"); + } + + @Test + public void testTypeArgumentsAreBackwardCompatibleForOldGrammarMissingIt() throws JsonProcessingException + { + testFormat("function test::new(): Any[1]\n" + + "{\n" + + " ^BasicColumnSpecification(func=r: TDSRow[1]|1)\n" + + "}\n", + "function test::new(): Any[1]\n" + + "{\n" + + " ^BasicColumnSpecification(func=r: TDSRow[1]|1)\n" + + "}\n"); + + testFormat("function test::new(res: Result[1]): Any[1]\n" + + "{\n" + + " 1\n" + + "}\n", + "function test::new(res: Result[1]): Any[1]\n" + + "{\n" + + " 1\n" + + "}\n"); } @Test diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java index b86bc90685c..0f3b4525226 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/Variable.java @@ -73,7 +73,7 @@ public ValueSpecification deserialize(JsonParser jsonParser, DeserializationCont Variable variable = new Variable(); variable.name = node.get("name").asText(); - // Backward compatibility ------------------------------------------------------------------- + // Backward compatibility - old protocol ------------------------------------------------------------------- if (node.get("class") != null) { String _class = node.get("class").asText(); @@ -85,11 +85,24 @@ public ValueSpecification deserialize(JsonParser jsonParser, DeserializationCont } variable.genericType = genericType; } - // Backward compatibility ------------------------------------------------------------------- + // Backward compatibility - old protocol ------------------------------------------------------------------- else if (node.get("genericType") != null) { variable.genericType = om.treeToValue(node.get("genericType"), GenericType.class); + + // Backward compatibility - old grammar ------------------------------------------------------------------- + if (variable.genericType.rawType instanceof PackageableType) + { + String _class = ((PackageableType) variable.genericType.rawType).fullPath; + if (("meta::pure::mapping::Result".equals(_class) || "Result".equals(_class)) && variable.genericType.typeArguments.size() == 0) + { + variable.genericType.typeArguments = Lists.mutable.of(new GenericType(new PackageableType("meta::pure::metamodel::type::Any"))); + variable.genericType.multiplicityArguments = Lists.mutable.of(Multiplicity.PURE_MANY); + } + } + // Backward compatibility - old grammar ------------------------------------------------------------------- + } if (node.get("multiplicity") != null) { diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java index 0dc3cc789ae..e03f00b8fbc 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/valueSpecification/application/AppliedFunction.java @@ -54,42 +54,58 @@ public static class AppliedFunctionConverter extends StdConverter classesThatNeedTypeFixing = Sets.fixedSize.of( - "meta::pure::tds::BasicColumnSpecification", - "BasicColumnSpecification", - "meta::pure::tds::TdsOlapRank", - "TdsOlapRank" - ); - if (classesThatNeedTypeFixing.contains(type.fullPath)) + type = (PackageableElementPtr) appliedFunction.parameters.get(0); + } + else + { + GenericTypeInstance typeInstance = (GenericTypeInstance) appliedFunction.parameters.get(0); + // Backward compatibility - old grammar ------------------------------------------------------------------- + if (typeInstance.genericType.typeArguments.size() == 1 && typeInstance.genericType.typeArguments.get(0).rawType instanceof PackageableType) { - Collection collection = (Collection) appliedFunction.parameters.get(2); - Optional func = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("func")) - .map(KeyExpression.class::cast) - .map(x -> x.expression) - .filter(Lambda.class::isInstance) - .map(Lambda.class::cast) - .filter(x -> x.parameters.size() == 1); + type = (PackageableType) typeInstance.genericType.typeArguments.get(0).rawType; + } + else + { + return appliedFunction; + } + } + + Set classesThatNeedTypeFixing = Sets.fixedSize.of( + "meta::pure::tds::BasicColumnSpecification", + "BasicColumnSpecification", + "meta::pure::tds::TdsOlapRank", + "TdsOlapRank" + ); + if (classesThatNeedTypeFixing.contains(type.fullPath)) + { + Collection collection = (Collection) appliedFunction.parameters.get(2); + Optional func = ListIterate.detectOptional(collection.values, x -> ((CString) ((KeyExpression) x).key).value.equals("func")) + .map(KeyExpression.class::cast) + .map(x -> x.expression) + .filter(Lambda.class::isInstance) + .map(Lambda.class::cast) + .filter(x -> x.parameters.size() == 1); - if (func.isPresent()) - { - Lambda l = func.get(); + if (func.isPresent()) + { + Lambda l = func.get(); - PackageableType rawType = new PackageableType(type.fullPath); - rawType.sourceInformation = type.sourceInformation; - List classType = Lists.mutable.of(new GenericType(rawType, Lists.mutable.with(l.parameters.get(0).genericType))); - GenericTypeInstance generic = new GenericTypeInstance(new GenericType(new PackageableType("meta::pure::metamodel::type::Class"), classType)); - appliedFunction.parameters.set(0, generic); - } + PackageableType rawType = new PackageableType(type.fullPath); + rawType.sourceInformation = type.sourceInformation; + List classType = Lists.mutable.of(new GenericType(rawType, Lists.mutable.with(l.parameters.get(0).genericType))); + GenericTypeInstance generic = new GenericTypeInstance(new GenericType(new PackageableType("meta::pure::metamodel::type::Class"), classType)); + appliedFunction.parameters.set(0, generic); } - // Backward compatibility ------------------------------------------------------------------- } } + // Backward compatibility ------------------------------------------------------------------- return appliedFunction; } }