Skip to content

Commit

Permalink
Protocol fixing when parsing old grammar
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelbey committed Nov 23, 2024
1 parent 0fa1690 commit ec991d6
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ public void testInFixFunctionAsParameter()
}

@Test
public void testNewConstructorWithTypeArgumentsIsBackwardCompatible() throws JsonProcessingException
public void testTypeArgumentsAreBackwardCompatibleForOldProtocolMissingIt() throws JsonProcessingException
{
testComposedGrammar("{\n" +
" \"_type\": \"data\",\n" +
Expand Down Expand Up @@ -603,28 +603,87 @@ 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" +
"}",
"function test::new(): Any[1]\n" +
"{\n" +
" ^BasicColumnSpecification<TDSRow>(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<meta::pure::metamodel::type::Any|1..*>[1]): Any[1]\n" +
"{\n" +
" 1\n" +
"}\n");
}

@Test
public void testTypeArgumentsAreBackwardCompatibleForOldGrammarMissingIt() throws JsonProcessingException
{
testFormat("function test::new(): Any[1]\n" +
"{\n" +
" ^BasicColumnSpecification<TDSRow>(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<meta::pure::metamodel::type::Any|1..*>[1]): Any[1]\n" +
"{\n" +
" 1\n" +
"}\n",
"function test::new(res: Result[1]): Any[1]\n" +
"{\n" +
" 1\n" +
"}\n");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,42 +54,58 @@ public static class AppliedFunctionConverter extends StdConverter<AppliedFunctio
@Override
public AppliedFunction convert(AppliedFunction appliedFunction)
{
// Backward compatibility -------------------------------------------------------------------
if (appliedFunction.function.equals("new"))
{
PackageableElementPtr type;
// Backward compatibility - old protocol -------------------------------------------------------------------
if (appliedFunction.parameters.get(0) instanceof PackageableElementPtr)
{
PackageableElementPtr type = (PackageableElementPtr) appliedFunction.parameters.get(0);
// Backward compatibility -------------------------------------------------------------------
Set<String> 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<Lambda> 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<String> 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<Lambda> 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<GenericType> 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<GenericType> 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;
}
}
Expand Down

0 comments on commit ec991d6

Please sign in to comment.