Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symbol DeSer: Fix subscopes & add SymTypeExpression generation #54

Merged
merged 6 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package de.monticore.codegen.cd2java._symboltable.serialization;

import de.monticore.generating.templateengine.HookPoint;
import de.monticore.types.check.SymTypeExpression;

import java.util.LinkedHashMap;
import java.util.Map;
Expand Down Expand Up @@ -49,6 +50,9 @@ public void init() {
bitsers.put("long", _long);
bitsers.put("java.lang.Long", _long);
bitsers.put("Long", _long);

BITSerStrategy symTypeExpression = new SymTypeExpressionSerStrategy();
bitsers.put(SymTypeExpression.class.getName(), symTypeExpression);
luepges marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -84,21 +88,22 @@ public Optional<HookPoint> getSerialHook(String attrType, String attrName) {
* @param attrType
* @param attrName
* @param jsonName
* @param scopeName the name of the scope parameter, such as scope or enclosingScope
* @return
*/
public Optional<HookPoint> getDeserialHook(String attrType, String attrName, String jsonName) {
public Optional<HookPoint> getDeserialHook(String attrType, String attrName, String jsonName, String scopeName) {
if (bitsers.containsKey(attrType)) {
return Optional.of(bitsers.get(attrType).getDeserialHook(jsonName, attrName));
return Optional.of(bitsers.get(attrType).getDeserialHook(jsonName, attrName, scopeName));
}

Optional<String> listGenType = getListGenType(attrType);
if (listGenType.isPresent() && bitsers.containsKey(listGenType.get())) {
return Optional.of(bitsers.get(listGenType.get()).getListDeserialHook(jsonName, attrName));
return Optional.of(bitsers.get(listGenType.get()).getListDeserialHook(jsonName, attrName, scopeName));
}

Optional<String> optGenType = getOptionalGenType(attrType);
if (optGenType.isPresent() && bitsers.containsKey(optGenType.get())) {
return Optional.of(bitsers.get(optGenType.get()).getOptDeserialHook(jsonName, attrName));
return Optional.of(bitsers.get(optGenType.get()).getOptDeserialHook(jsonName, attrName, scopeName));
}

return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ public HookPoint getListSerialHook(String attrParam) {
return new TemplateHookPoint(PRINT_LIST_TEMPLATE, attrParam);
}

public HookPoint getDeserialHook(String jsonParam, String attrParam) {
public HookPoint getDeserialHook(String jsonParam, String attrParam, String scopeName) {
String typeMap = ".get" + type + "MemberOpt(\"" + attrParam + "\").orElse("+defaultValue+");";
return new StringHookPoint("return " + jsonParam + typeMap);
}

public HookPoint getOptDeserialHook(String jsonParam, String attrParam) {
public HookPoint getOptDeserialHook(String jsonParam, String attrParam, String scopeName) {
String typeMap = "get" + type + "Member(\"" + attrParam + "\")";
return new TemplateHookPoint(READ_OPT_TEMPLATE, jsonParam, attrParam, typeMap);
}

public HookPoint getListDeserialHook(String jsonParam, String attrParam) {
public HookPoint getListDeserialHook(String jsonParam, String attrParam, String scopeName) {
String typeMap;
if(type.equals("String") || type.equals("Boolean")){
typeMap = "getAsJson" + type + "().getValue()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ protected List<ASTCDMethod> createDeserializeAttrMethods(

// Check whether built-in serialization exists. If yes, use it and otherwise make method abstract
Optional<HookPoint> impl = bitser
.getDeserialHook(attr.printType(), attr.getName(), "scopeJson");
.getDeserialHook(attr.printType(), attr.getName(), "scopeJson", scopeParam.getName());
if (impl.isPresent()) {
this.replaceTemplate(EMPTY_BODY, method, impl.get());
String deprecatedWrapperImpl = "return this." + methodName +
Expand Down Expand Up @@ -301,7 +301,8 @@ protected Map<String, Boolean> createSymbolMap(ASTCDDefinition symbolInput) {
//add local symbols
for (ASTCDType prod : symbolTableService.getSymbolDefiningProds(symbolInput)) {
String name = symbolTableService.getSymbolFullName(prod);
boolean spansScope = symbolTableService.hasScopeStereotype(prod.getModifier());
boolean spansScope = symbolTableService.hasScopeStereotype(prod.getModifier())
|| symbolTableService.hasInheritedScopeStereotype(prod.getModifier());
symbolMap.put(name, spansScope);
}

Expand All @@ -311,8 +312,8 @@ protected Map<String, Boolean> createSymbolMap(ASTCDDefinition symbolInput) {
if (type.isPresentAstNode() && symbolTableService.hasSymbolStereotype(type.getAstNode().getModifier())) {
String name = symbolTableService
.getSymbolFullName(type.getAstNode(), cdDefinitionSymbol);
boolean spansScope = symbolTableService
.hasScopeStereotype(type.getAstNode().getModifier());
boolean spansScope = symbolTableService.hasScopeStereotype(type.getAstNode().getModifier())
|| symbolTableService.hasInheritedScopeStereotype(type.getAstNode().getModifier());
symbolMap.put(name, spansScope);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.codegen.cd2java._symboltable.serialization;

import de.monticore.generating.templateengine.HookPoint;
import de.monticore.generating.templateengine.StringHookPoint;
import de.monticore.types.check.SymTypeExpression;

/**
* DeSerialization of {@link SymTypeExpression} symbol attributes.
*/
public class SymTypeExpressionSerStrategy extends BITSerStrategy {
public SymTypeExpressionSerStrategy() {
super(SymTypeExpression.class.getName(), "null");
}

@Override
public HookPoint getSerialHook(String attrParam) {
return new StringHookPoint(String.format("de.monticore.types.check.SymTypeExpressionDeSer.serializeMember(s2j.getJsonPrinter(), \"%s\", %s);", attrParam, attrParam));
}

@Override
public HookPoint getOptSerialHook(String attrParam) {
return new StringHookPoint(String.format("de.monticore.types.check.SymTypeExpressionDeSer.serializeMember(s2j.getJsonPrinter(), \"%s\", %s);", attrParam, attrParam));
}

@Override
public HookPoint getListSerialHook(String attrParam) {
return new StringHookPoint(String.format("de.monticore.types.check.SymTypeExpressionDeSer.serializeMember(s2j.getJsonPrinter(), \"%s\", %s);", attrParam, attrParam));
}

@Override
public HookPoint getDeserialHook(String jsonParam, String attrParam, String scopeName) {
return new StringHookPoint(String.format("return de.monticore.types.check.SymTypeExpressionDeSer.deserializeMember(\"%s\", %s, %s);", attrParam, jsonParam, scopeName));
luepges marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public HookPoint getOptDeserialHook(String jsonParam, String attrParam, String scopeName) {
return new StringHookPoint(String.format("return de.monticore.types.check.SymTypeExpressionDeSer.deserializeOptionalMember(\"%s\", %s, %s);", attrParam, jsonParam, scopeName));
}

@Override
public HookPoint getListDeserialHook(String jsonParam, String attrParam, String scopeName) {
return new StringHookPoint(String.format("return de.monticore.types.check.SymTypeExpressionDeSer.deserializeListMember(\"%s\", %s, %s);", attrParam, jsonParam, scopeName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ protected List<ASTCDMethod> createDeserializeAttrMethods(

// Check whether built-in serialization exists. If yes, use it and otherwise make method abstract
Optional<HookPoint> impl = bitser
.getDeserialHook(attr.printType(), attr.getName(), "symbolJson");
.getDeserialHook(attr.printType(), attr.getName(), "symbolJson", scopeParam.getName());
if (impl.isPresent()) {
this.replaceTemplate(EMPTY_BODY, method, impl.get());
String deprecatedWrapperImpl = "return this." + methodName +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ component grammar OOSymbols extends BasicSymbols {
* The new symbol MethodSymbol inherits from FunctionSymbol and
* mainly adds OO specific properties.
*/
interface scope symbol Method extends Function = Name ;
interface symbol Method extends Function = Name ;

symbolrule Method =
isConstructor: boolean
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* (c) https://github.com/MontiCore/monticore */
grammar SystematicScopeDeSer extends de.monticore.MCBasics, de.monticore.symbols.OOSymbols {

CompilationUnit = MyScopeSymbolI* Method* Function*;
start CompilationUnit;

// Defines scope & interface
interface symbol scope MyScopeSymbolI = Name;

// In the symbol table, this is actually a MyScopeSymbolI
interface MyScopeSymbolI2 extends MyScopeSymbolI = Name;

// All of the following productions are symbols which span a scope
// Some explicitly define a "new" symbol, while others are MyScopeSymbolI-symbols
MyScopeSymbolIImpl1 implements MyScopeSymbolI = Name; // MyScopeSymbolI symbol
symbol MyScopeSymbolIImpl2 implements MyScopeSymbolI = Name; // new symbol
symbol scope MyScopeSymbolIImpl3 implements MyScopeSymbolI = Name; // new symbol

MyScopeSymbolI2Impl1 implements MyScopeSymbolI2 = Name; // MyScopeSymbolI symbol
symbol MyScopeSymbolI2Impl2 implements MyScopeSymbolI2 = Name; // new symbol
symbol scope MyScopeSymbolI2Impl3 implements MyScopeSymbolI2 = Name; // new symbol

// Also test using OO/Basic symbols
TestMethod implements Method = "method" Name;
TestFunction implements Function = "function" Name;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* (c) https://github.com/MontiCore/monticore */
import de.monticore.symbols.basicsymbols._symboltable.FunctionSymbol;
import de.monticore.symbols.oosymbols._symboltable.MethodSymbol;
import de.monticore.types.check.SymTypeObscure;
import de.se_rwth.commons.logging.LogStub;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import systematicscopedeser.SystematicScopeDeSerMill;
import systematicscopedeser._symboltable.*;

/**
* Test that the DeSer correctly handles inherited scope/symbols
* as well as their subscopes
*/
public class SystematicDeSerTest {

@BeforeAll
public static void init() {
LogStub.init();
LogStub.clearFindings();

SystematicScopeDeSerMill.init();
}

@Test
public void test() {
// Construct one of each symbol
var compU = SystematicScopeDeSerMill.compilationUnitBuilder();

// direct implementations of interface symbol scope MyScopeSymbolI
var i1 = SystematicScopeDeSerMill.myScopeSymbolIImpl1Builder().setName("i1").build();
compU.addMyScopeSymbolI(i1);
var i2 = SystematicScopeDeSerMill.myScopeSymbolIImpl2Builder().setName("i2").build();
compU.addMyScopeSymbolI(i2);
var i3 = SystematicScopeDeSerMill.myScopeSymbolIImpl3Builder().setName("i3").build();
compU.addMyScopeSymbolI(i3);

// indirect implementations of interface MyScopeSymbolI2 extends MyScopeSymbolI
var s1 = SystematicScopeDeSerMill.myScopeSymbolI2Impl1Builder().setName("s1").build();
compU.addMyScopeSymbolI(s1);
var s2 = SystematicScopeDeSerMill.myScopeSymbolI2Impl2Builder().setName("s2").build();
compU.addMyScopeSymbolI(s2);
var s3 = SystematicScopeDeSerMill.myScopeSymbolI2Impl3Builder().setName("s3").build();
compU.addMyScopeSymbolI(s3);
var m = SystematicScopeDeSerMill.testMethodBuilder().setName("m").build();
compU.addMethod(m);
var f = SystematicScopeDeSerMill.testFunctionBuilder().setName("f").build();
compU.addFunction(f);

var ast = compU.build();

var scope = SystematicScopeDeSerMill.scopesGenitorDelegator().createFromAST(ast);

// Set some SymTypeExpression information for the type field
m.getSymbol().setType(new SymTypeObscure());
f.getSymbol().setType(new SymTypeObscure());

Assertions.assertEquals(8, scope.getSubScopes().size());
// Test that the symbols are correct
Assertions.assertEquals(MyScopeSymbolISymbol.class, i1.getSymbol().getClass());
Assertions.assertEquals(MyScopeSymbolIImpl2Symbol.class, i2.getSymbol().getClass());
Assertions.assertEquals(MyScopeSymbolIImpl3Symbol.class, i3.getSymbol().getClass());
Assertions.assertEquals(MyScopeSymbolISymbol.class, s1.getSymbol().getClass());
Assertions.assertEquals(MyScopeSymbolI2Impl2Symbol.class, s2.getSymbol().getClass());
Assertions.assertEquals(MyScopeSymbolI2Impl3Symbol.class, s3.getSymbol().getClass());
Assertions.assertEquals(MethodSymbol.class, m.getSymbol().getClass());
Assertions.assertEquals(FunctionSymbol.class, f.getSymbol().getClass());

var s2j = new SystematicScopeDeSerSymbols2Json();

String serialized = s2j.serialize(scope);

// And now, do similar tests on the serialized & deserialized symbol table

var scope2 = s2j.deserialize(serialized);

Assertions.assertEquals(8, scope2.getSubScopes().size());
// Test that the symbols are present && correct
Assertions.assertEquals(MyScopeSymbolISymbol.class, scope2.resolveMyScopeSymbolI("i1").get().getClass());
Assertions.assertEquals(MyScopeSymbolIImpl2Symbol.class, scope2.resolveMyScopeSymbolIImpl2("i2").get().getClass());
Assertions.assertEquals(MyScopeSymbolIImpl3Symbol.class, scope2.resolveMyScopeSymbolIImpl3("i3").get().getClass());
Assertions.assertEquals(MyScopeSymbolISymbol.class, scope2.resolveMyScopeSymbolI("s1").get().getClass());
Assertions.assertEquals(MyScopeSymbolI2Impl2Symbol.class, scope2.resolveMyScopeSymbolI2Impl2("s2").get().getClass());
Assertions.assertEquals(MyScopeSymbolI2Impl3Symbol.class, scope2.resolveMyScopeSymbolI2Impl3("s3").get().getClass());
Assertions.assertEquals(MethodSymbol.class, scope2.resolveMethod("m").get().getClass());
Assertions.assertEquals(FunctionSymbol.class, scope2.resolveFunction("f").get().getClass());

// Note: We will have findings in our log due to SymTypeObscure
}


}
Loading