From 741ad34a5f1404dc5eb4673d28054525db4907b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 4 Sep 2026 20:03:51 +0200 Subject: [PATCH 01/21] SymTypeExpression and wrappers return a supplier in case the symbol can not be resolved immediatly --- .../codegen/cd2java/DecorationHelper.java | 68 +++++++++++++++++-- .../_symboltable/symbol/SymbolDecorator.java | 7 ++ .../cd2java/methods/AccessAsSupplierTyps.java | 22 ++++++ .../cd2java/methods/ListMethodDecorator.java | 8 ++- .../methods/SpecificMethodDecorator.java | 13 +++- .../accessor/ListAccessorDecorator.java | 10 ++- .../accessor/MandatoryAccessorDecorator.java | 12 +++- .../accessor/OptionalAccessorDecorator.java | 24 ++++++- .../methods/mutator/ListMutatorDecorator.java | 10 ++- .../mutator/MandatoryMutatorDecorator.java | 15 +++- .../mutator/OptionalMutatorDecorator.java | 26 +++++-- .../main/resources/methods/SupplierGet.ftl | 7 ++ .../main/resources/methods/SupplierSet.ftl | 5 ++ .../resources/methods/opt/SupplierGet4Opt.ftl | 8 +++ .../methods/opt/SupplierIsPresent4Opt.ftl | 7 ++ .../resources/methods/opt/SupplierSet4Opt.ftl | 5 ++ .../methods/opt/SupplierSetAbsent.ftl | 5 ++ .../basicsymbols/_symboltable/TypeSymbol.java | 4 +- .../_symboltable/VariableSymbol.java | 5 +- .../ComponentType2TypeSymbolAdapter.java | 4 +- .../compsymbols/_symboltable/PortSymbol.java | 9 +-- .../oosymbols/_symboltable/MethodSymbol.java | 2 +- .../oosymbols/_symboltable/OOTypeSymbol.java | 6 +- .../mc/feature/symbolrules/SymbolruleTest.mc4 | 2 +- 24 files changed, 246 insertions(+), 38 deletions(-) create mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java create mode 100644 monticore-generator/src/main/resources/methods/SupplierGet.ftl create mode 100644 monticore-generator/src/main/resources/methods/SupplierSet.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 56f5dec0db..cf2b11d45a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -13,6 +13,9 @@ import de.monticore.generating.templateengine.StringHookPoint; import de.monticore.symboltable.ISymbol; import de.monticore.types.MCBasicTypesHelper; +import de.monticore.types.MCTypeFacade; +import de.monticore.types.mccollectiontypes._ast.ASTMCListType; +import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.types.mcbasictypes._ast.ASTMCPrimitiveType; import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType; @@ -31,6 +34,7 @@ import static de.monticore.cd.codegen.CD2JavaTemplates.VALUE; import static de.monticore.codegen.cd2java._ast.ast_class.ASTConstants.AST_PREFIX; +import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps.SUPPLIER_TYPE; public class DecorationHelper extends MCBasicTypesHelper { @@ -67,7 +71,7 @@ public boolean isAstNode(ASTCDAttribute attr) { } public boolean isSimpleAstNode(ASTCDAttribute attr) { - return !isOptional(attr.getMCType()) && !isListType(attr.printType()) && isAstNode(attr); + return !isOptional(attr.getMCType()) && !isList(attr.getMCType()) && isAstNode(attr); } public boolean isOptionalAstNode(ASTCDAttribute attr) { @@ -75,7 +79,7 @@ public boolean isOptionalAstNode(ASTCDAttribute attr) { } public boolean isListAstNode(ASTCDAttribute attribute) { - return isListType(attribute.printType()) && isAstNode(attribute); + return isList(attribute.getMCType()) && isAstNode(attribute); } public boolean isListType(String type) { @@ -113,6 +117,25 @@ public boolean isOptional(ASTMCType type) { return false; } + public boolean isList(ASTMCType type) { + if (type instanceof ASTMCListType) { + return true; + } else if (type instanceof ASTMCGenericType) { + String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); + return "List".equals(Names.getSimpleName(simpleType)); + } + return false; + } + + public boolean isSupplier(ASTMCType type) { + if (type instanceof ASTMCGenericType) { + String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); + return "Supplier".equals(Names.getSimpleName(simpleType)); + } + return false; + } + + public boolean isString(String type) { return "String".equals(type) || "java.lang.String".equals(type); } @@ -159,12 +182,34 @@ public String getSimpleNativeType(String nativeAttributeType) { * important for Optional and List types */ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionManagement glex) { - if (isListType(attribute.printType())) { - glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= new java.util.ArrayList<>()")); + // For a wrapped attribute (Supplier) the default is derived from the unwrapped type X. + ASTMCType type = attribute.getMCType(); + boolean isSupplier = isSupplier(type); + if (isSupplier) { + type = getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } - } else if (isOptional(attribute.getMCType())) { - glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= Optional.empty()")); + String inner; + if (isList(type)) { + inner = "new java.util.ArrayList<>()"; + } else if (isOptional(type)) { + inner = "Optional.empty()"; + } else if (isSupplier) { + inner = "null"; + } else { + return; } + + String defaultValue; + if (!isSupplier) { + defaultValue = "= " + inner; + } else if (isList(type)) { + // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. + defaultValue = "= com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; + } else { + defaultValue = "= () -> " + inner; + } + glex.replaceTemplate(VALUE, attribute, new StringHookPoint(defaultValue)); } /** @@ -184,6 +229,17 @@ public ASTMCTypeArgument getReferenceTypeFromOptional(ASTMCType type) { return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); } + public ASTMCTypeArgument getReferenceTypeFromSupply(ASTMCType type) { + Preconditions.checkArgument(isSupplier(type)); + return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); + } + + public ASTMCType createSupplierTypeOf(ASTMCType inner) { + ASTMCTypeArgument arg = MCSimpleGenericTypesMill + .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); + return MCTypeFacade.getInstance().createBasicGenericTypeOf(SUPPLIER_TYPE, arg); + } + /** * methods only used in templates */ diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index 3db0ee80ff..06c60f497c 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -14,6 +14,7 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -90,6 +91,12 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { .filter(attr -> !symbolTableService.isInheritedAttribute(attr)) .map(a -> a.deepClone()) .collect(Collectors.toList()); + + // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later + symbolRuleAttributes.stream() + .filter(a -> AccessAsSupplierTyps.shouldBeSupplied(a.getMCType().printType())) + .forEach(a -> a.setMCType(getDecorationHelper().createSupplierTypeOf(a.getMCType()))); + symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); List symbolRuleAttributeMethods = symbolRuleAttributes .stream() diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java new file mode 100644 index 0000000000..871e675df9 --- /dev/null +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java @@ -0,0 +1,22 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.codegen.cd2java.methods; + +import java.util.Arrays; + + +public class AccessAsSupplierTyps { + + public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; + + // TODO also accept non-fully-qualified spellings + public static final String[] SUPPLYLIST = { + "de.monticore.types.check.SymTypeExpression", + "java.util.List", + "java.util.Optional" + }; + + + public static boolean shouldBeSupplied(String t) { + return Arrays.asList(SUPPLYLIST).contains(t); + } +} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java index e193305c0d..1125d19c4a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java @@ -83,6 +83,12 @@ public String getCapitalizedAttributeNameWithS(ASTCDAttribute attribute) { } public String getAttributeType(ASTCDAttribute attribute) { - return getTypeArgumentFromListType(attribute.getMCType()); + ASTMCType type = attribute.getMCType(); + + if (getDecorationHelper().isSupplier(type)) { + // a wrapped list attribute has the shape Supplier> -> unwrap to List before extracting X + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } + return getTypeArgumentFromListType(type); } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java index a88d4507f7..55378a921c 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java @@ -5,6 +5,7 @@ import de.monticore.cd4codebasis._ast.ASTCDMethod; import de.monticore.codegen.cd2java.AbstractCreator; import de.monticore.generating.templateengine.GlobalExtensionManagement; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import java.util.List; @@ -47,11 +48,17 @@ public List decorate(final ASTCDAttribute ast) { } protected AbstractCreator> determineMethodDecoratorStrategy(final ASTCDAttribute ast) { - if (getMCTypeFacade().isBooleanType(ast.getMCType())) { + // If the type is wrapped (supplier), unwrap for determination + ASTMCType type = ast.getMCType(); + if (getDecorationHelper().isSupplier(type)) { + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } + + if (getMCTypeFacade().isBooleanType(type)) { return mandatoryMethodDecorator; - } else if (getDecorationHelper().isListType(ast.printType())) { + } else if (getDecorationHelper().isList(type)) { return listMethodDecorator; - } else if (getDecorationHelper().isOptional(ast.getMCType())) { + } else if (getDecorationHelper().isOptional(type)) { return optionalMethodDecorator; } return mandatoryMethodDecorator; diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java index 2c7004272d..302dcb415b 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java @@ -49,7 +49,15 @@ public List decorate(ASTCDAttribute ast) { protected ASTCDMethod createGetListMethod(ASTCDAttribute ast) { String signature = String.format(GET_LIST, attributeType, capitalizedAttributeNameWithOutS); ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature); - this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Get", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + templateName = "methods.SupplierGet"; + } else { + templateName = "methods.Get"; + } + + this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint(templateName, ast)); return getList; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index 214c2f2154..8956a77916 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -41,8 +41,18 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { } String name = String.format(getterPrefix, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); ASTMCType type = ast.getMCType().deepClone(); + + String templateName; + if (getDecorationHelper().isSupplier(type)) { + // The Supplier is hidden from the user. The getter has to expose the unwrapped type (Supplier -> X) + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + templateName = "methods.SupplierGet"; + } else { + templateName = "methods.Get"; + } + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.Get", ast)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index 0107da56fb..fea7b20524 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -48,17 +48,35 @@ protected String getNaiveAttributeName(ASTCDAttribute astcdAttribute) { protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String name = String.format(GET, naiveAttributeName); - ASTMCType type = getDecorationHelper().getReferenceTypeFromOptional(ast.getMCType().deepClone()).getMCTypeOpt().get(); + + ASTMCType type = ast.getMCType().deepClone(); + String templateName; + if (getDecorationHelper().isSupplier(type)){ + templateName = "methods.opt.SupplierGet4Opt"; + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } else { + templateName = "methods.opt.Get4Opt"; + } + + type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get(); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); String generatedErrorCode = service.getGeneratedErrorCode(ast.getName() + ast.printType()); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.Get4Opt", ast, naiveAttributeName, generatedErrorCode)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName, generatedErrorCode)); return method; } protected ASTCDMethod createIsPresentMethod(final ASTCDAttribute ast) { String name = String.format(IS_PRESENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), getMCTypeFacade().createBooleanType(), name); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.IsPresent4Opt", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())){ + templateName = "methods.opt.SupplierIsPresent4Opt"; + } else { + templateName = "methods.opt.IsPresent4Opt"; + } + + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java index 603a983390..ac932899ff 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java @@ -44,7 +44,15 @@ public List decorate(ASTCDAttribute ast) { protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { String signature = String.format(SET_LIST, capitalizedAttributeNameWithOutS, attributeType, ast.getName()); ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature); - this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Set", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + templateName = "methods.SupplierSet"; + } else { + templateName = "methods.Set"; + } + + this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint(templateName, ast)); return getList; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java index f1b324e238..41439ff3c7 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java @@ -29,9 +29,18 @@ public List decorate(final ASTCDAttribute ast) { } protected ASTCDMethod createSetter(final ASTCDAttribute ast) { - String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); - ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, this.getCDParameterFacade().createParameters(ast)); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.Set", ast)); + ASTCDAttribute attribute = ast; + String templateName = "methods.Set"; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + // expose the unwrapped type (Supplier -> X) in the setter parameter; the Supplier stays hidden + attribute = ast.deepClone(); + attribute.setMCType(getDecorationHelper().getReferenceTypeFromSupply(attribute.getMCType()).getMCTypeOpt().get()); + templateName = "methods.SupplierSet"; + } + + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index a11baf943a..081fcd24b2 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -39,17 +39,35 @@ public List decorate(final ASTCDAttribute ast) { protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeFromOptional(ast.getMCType()).getMCTypeOpt().get().deepClone(); - ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, ast.getName()); + + ASTMCType type = ast.getMCType().deepClone(); + String templateName; + if (getDecorationHelper().isSupplier(type)){ + templateName = "methods.opt.SupplierSet4Opt"; + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } else { + templateName = "methods.opt.Set4Opt"; + } + + type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get().deepClone(); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(type, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.Set4Opt", ast, naiveAttributeName)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName)); return method; } protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute ast) { String name = String.format(SET_ABSENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.SetAbsent", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())){ + templateName = "methods.opt.SupplierSetAbsent"; + } else { + templateName = "methods.opt.SetAbsent"; + } + + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/resources/methods/SupplierGet.ftl b/monticore-generator/src/main/resources/methods/SupplierGet.ftl new file mode 100644 index 0000000000..44470de684 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/SupplierGet.ftl @@ -0,0 +1,7 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +var __value = this.${attribute.getName()}.get(); +if (__value == null) { + throw new IllegalStateException("Value of '${attribute.getName()}' is not available yet."); +} +return __value; diff --git a/monticore-generator/src/main/resources/methods/SupplierSet.ftl b/monticore-generator/src/main/resources/methods/SupplierSet.ftl new file mode 100644 index 0000000000..41e8259e86 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/SupplierSet.ftl @@ -0,0 +1,5 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = () -> ${attribute.getName()}; +${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl new file mode 100644 index 0000000000..ac245b7d34 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl @@ -0,0 +1,8 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute", "naiveAttributeName", "generatedErrorCode")} + if (isPresent${naiveAttributeName}()) { + return this.${attribute.getName()}.get().get(); + } + Log.error("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); + // Normally this statement is not reachable + throw new IllegalStateException(); diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl new file mode 100644 index 0000000000..adcb16fcd6 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl @@ -0,0 +1,7 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +var optional = this.${attribute.getName()}.get(); +if (optional == null){ + throw new IllegalStateException("supplier for ${attribute.getName()} is null"); +} +return optional.isPresent(); diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl new file mode 100644 index 0000000000..69d9a84eed --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl @@ -0,0 +1,5 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute", "nativeAttributeName")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = () -> Optional.ofNullable(${attribute.getName()}); +${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl new file mode 100644 index 0000000000..9a899540ca --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl @@ -0,0 +1,5 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = () -> Optional.empty(); +${defineHookPoint("Setter:After")} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java index df33675d64..e7484e3857 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java @@ -21,11 +21,11 @@ public void setFunctionList(List methodList){ } public List getSuperClassesOnly(){ - return superTypes; + return superTypes.get(); } public List getInterfaceList(){ - return superTypes; + return superTypes.get(); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java index 328818c74a..3fa23d4911 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java @@ -22,8 +22,9 @@ public VariableSymbol deepClone(){ if(isPresentAstNode()) { clone.setAstNode(this.getAstNode()); } - if(type!=null){ - clone.setType(type.deepClone()); + SymTypeExpression t = getType(); + if(t!=null){ + clone.setType(t.deepClone()); } return clone; } diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java index 0458e3960b..70578ae6d9 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java @@ -20,7 +20,7 @@ public ComponentType2TypeSymbolAdapter(@NonNull ComponentTypeSymbol adaptee) { this.adaptee = adaptee; this.accessModifier = BasicAccessModifier.PUBLIC; this.spannedScope = adaptee.getSpannedScope(); - this.superTypes = adaptee.getSuperComponentsList().stream().map(c -> { + setSuperTypesList(adaptee.getSuperComponentsList().stream().map(c -> { if (!c.isGenericComponentType()) { return SymTypeExpressionFactory.createTypeObject(new ComponentType2TypeSymbolAdapter(c.getTypeInfo())); } else { @@ -28,7 +28,7 @@ public ComponentType2TypeSymbolAdapter(@NonNull ComponentTypeSymbol adaptee) { new ComponentType2TypeSymbolAdapter(c.getTypeInfo()), c.asGenericComponentType().getTypeBindingsAsList() ); } - }).collect(Collectors.toList()); + }).collect(Collectors.toList())); } public ComponentTypeSymbol getAdaptee() { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java index f2066aa0dd..1b26b798ac 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java @@ -27,7 +27,7 @@ protected PortSymbol(String name, SymTypeExpression type, Timing timing) { super(name); - this.type = type; + setType(type); this.timing = timing; this.incoming = incoming; this.outgoing = outgoing; @@ -38,13 +38,14 @@ public boolean isTypePresent() { } public SymTypeExpression getType() { - Preconditions.checkState(this.type != null); - return this.type; + SymTypeExpression t = super.getType(); + Preconditions.checkState(t != null); + return t; } public void setType(@NonNull SymTypeExpression type) { Preconditions.checkNotNull(type); - this.type = type; + super.setType(type); } public TypeSymbol getTypeInfo() { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java index f9809f094b..ae7afb1d41 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java @@ -18,7 +18,7 @@ public MethodSymbol(String name) { */ public MethodSymbol deepClone() { MethodSymbol clone = new MethodSymbol(name); - clone.setType(this.type.deepClone()); + clone.setType(getType().deepClone()); clone.setEnclosingScope(this.enclosingScope); clone.setFullName(this.fullName); clone.setIsConstructor(this.isConstructor); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java index aee28c83b7..b99f861370 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java @@ -99,17 +99,17 @@ public SymTypeExpression getSuperClass() { public List getSuperClassesOnly() { List normalSuperTypes = super.getSuperClassesOnly().stream() .filter(type -> !(type.getTypeInfo() instanceof OOTypeSymbol)).collect(Collectors.toList()); - List oOSuperTypes = superTypes.stream() + List oOSuperTypes = getSuperTypesList().stream() .filter(type -> type.getTypeInfo() instanceof OOTypeSymbol) .filter(type -> ((OOTypeSymbol) type.getTypeInfo()).isIsClass()) - .collect(Collectors.toList()); + .toList(); normalSuperTypes.addAll(oOSuperTypes); return normalSuperTypes; } @Override public List getInterfaceList() { - return superTypes.stream() + return getSuperTypesList().stream() .filter(type -> type.getTypeInfo() instanceof OOTypeSymbol) .filter(type -> ((OOTypeSymbol) type.getTypeInfo()).isIsInterface()) .collect(Collectors.toList()); diff --git a/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 b/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 index 6b19ce2ceb..79ae74bcf8 100644 --- a/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 +++ b/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 @@ -22,7 +22,7 @@ grammar SymbolruleTest extends de.monticore.MCBasics, de.monticore.symbols.Basic symbolrule ITest = superTypes:de.monticore.types.check.SymTypeExpression* method public de.monticore.types.check.SymTypeExpression getByName(String name){ java.util.Optional expr = Optional.empty(); - for(de.monticore.types.check.SymTypeExpression symType:superTypes){ + for(de.monticore.types.check.SymTypeExpression symType:getSuperTypesList()){ if(symType.print().equals(name)){ expr = Optional.of(symType); } From d590008623318387b2b5b384f18c0118c9c40d78 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Thu, 10 Sep 2026 09:53:03 +0200 Subject: [PATCH 02/21] PR feedback --- .../codegen/cd2java/DecorationHelper.java | 73 +++++++++---------- ...erencedDefinitionOptAccessorDecorator.java | 2 +- .../BuilderOptionalMutatorDecorator.java | 2 +- ...eritedBuilderOptionalMutatorDecorator.java | 2 +- .../_symboltable/symbol/SymbolDecorator.java | 4 +- .../methods/AccessAsSupplierTypes.java | 38 ++++++++++ .../cd2java/methods/AccessAsSupplierTyps.java | 22 ------ .../cd2java/methods/ListMethodDecorator.java | 2 +- .../methods/SpecificMethodDecorator.java | 2 +- .../cd2java/methods/__internal__Supplier.java | 17 +++++ .../accessor/MandatoryAccessorDecorator.java | 2 +- .../accessor/OptionalAccessorDecorator.java | 5 +- .../mutator/MandatoryMutatorDecorator.java | 2 +- .../mutator/OptionalMutatorDecorator.java | 4 +- .../data/DeepCloneWithParameters.ftl | 2 +- .../basicsymbols/_symboltable/TypeSymbol.java | 4 +- .../java/de/monticore/types/MCTypeFacade.java | 24 ++++++ 17 files changed, 131 insertions(+), 76 deletions(-) create mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java delete mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java create mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index cf2b11d45a..b292019847 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -14,13 +14,11 @@ import de.monticore.symboltable.ISymbol; import de.monticore.types.MCBasicTypesHelper; import de.monticore.types.MCTypeFacade; -import de.monticore.types.mccollectiontypes._ast.ASTMCListType; -import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.types.mcbasictypes._ast.ASTMCPrimitiveType; import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType; -import de.monticore.types.mccollectiontypes._ast.ASTMCOptionalType; import de.monticore.types.mccollectiontypes._ast.ASTMCTypeArgument; +import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.umlmodifier._ast.ASTModifier; import de.monticore.umlstereotype._ast.ASTStereoValue; import de.monticore.umlstereotype._ast.ASTStereotype; @@ -34,7 +32,7 @@ import static de.monticore.cd.codegen.CD2JavaTemplates.VALUE; import static de.monticore.codegen.cd2java._ast.ast_class.ASTConstants.AST_PREFIX; -import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps.SUPPLIER_TYPE; +import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes.SUPPLIER_TYPE; public class DecorationHelper extends MCBasicTypesHelper { @@ -104,35 +102,29 @@ public boolean isOptional(String type) { if (index != -1) { type = type.substring(0, index); } - return "Optional".equals(type) || "java.lang.Optional".equals(type); + return "Optional".equals(Names.getSimpleName(type)); } - public boolean isOptional(ASTMCType type) { - if (type instanceof ASTMCOptionalType) { - return true; - } else if (type instanceof ASTMCGenericType) { - String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); - return "Optional".equals(Names.getSimpleName(simpleType)); + public boolean isSupplier(String type) { + int index = type.indexOf('<'); + if (index != -1) { + type = type.substring(0, index); } - return false; + return "Supplier".equals(Names.getSimpleName(type)); + } + + // The ASTMCType overloads intentionally delegate to the String checks above instead of using + // instanceof: a single implementation, and no reliance on the concrete AST node (see PR #372 review). + public boolean isOptional(ASTMCType type) { + return isOptional(type.printType()); } public boolean isList(ASTMCType type) { - if (type instanceof ASTMCListType) { - return true; - } else if (type instanceof ASTMCGenericType) { - String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); - return "List".equals(Names.getSimpleName(simpleType)); - } - return false; + return isListType(type.printType()); } public boolean isSupplier(ASTMCType type) { - if (type instanceof ASTMCGenericType) { - String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); - return "Supplier".equals(Names.getSimpleName(simpleType)); - } - return false; + return isSupplier(type.printType()); } @@ -186,11 +178,12 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM ASTMCType type = attribute.getMCType(); boolean isSupplier = isSupplier(type); if (isSupplier) { - type = getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } + boolean isList = isList(type); String inner; - if (isList(type)) { + if (isList) { inner = "new java.util.ArrayList<>()"; } else if (isOptional(type)) { inner = "Optional.empty()"; @@ -200,16 +193,17 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM return; } + // the initialization expression that is placed after the '=' of the field declaration String defaultValue; - if (!isSupplier) { - defaultValue = "= " + inner; - } else if (isList(type)) { - // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. - defaultValue = "= com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; - } else { - defaultValue = "= () -> " + inner; - } - glex.replaceTemplate(VALUE, attribute, new StringHookPoint(defaultValue)); + if (!isSupplier) { + defaultValue = inner; + } else if (isList) { + // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. + defaultValue = "com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; + } else { + defaultValue = "() -> " + inner; + } + glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= " + defaultValue)); } /** @@ -224,16 +218,21 @@ public String getNativeAttributeName(String attributeName) { return attributeName.substring(JavaNamesHelper.PREFIX_WHEN_WORD_IS_RESERVED.length()); } - public ASTMCTypeArgument getReferenceTypeFromOptional(ASTMCType type) { + public ASTMCTypeArgument getReferenceTypeOfOptional(ASTMCType type) { Preconditions.checkArgument(isOptional(type)); return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); } - public ASTMCTypeArgument getReferenceTypeFromSupply(ASTMCType type) { + public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { Preconditions.checkArgument(isSupplier(type)); return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); } + /** + * Wraps {@code inner} into {@code Supplier} + * + * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... + */ public ASTMCType createSupplierTypeOf(ASTMCType inner) { ASTMCTypeArgument arg = MCSimpleGenericTypesMill .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java index f59b247c53..077b089df6 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java @@ -43,7 +43,7 @@ protected String getNaiveAttributeName(ASTCDAttribute astcdAttribute) { @Override protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String name = String.format(GET, StringUtils.capitalize(naiveAttributeName)); - ASTMCType type = getDecorationHelper().getReferenceTypeFromOptional(ast.getMCType().deepClone()).getMCTypeOpt().get(); + ASTMCType type = getDecorationHelper().getReferenceTypeOfOptional(ast.getMCType().deepClone()).getMCTypeOpt().get(); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); String referencedSymbolType = symbolTableService.getReferencedSymbolTypeName(ast); String attributeName = this.getDecorationHelper().getNativeAttributeName(ast.getName()); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java index 58a7d8592e..147a826c44 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java @@ -30,7 +30,7 @@ public BuilderOptionalMutatorDecorator(final GlobalExtensionManagement glex, @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeFromOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); + ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java index 70d14d4f7e..b6df5bc534 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java @@ -28,7 +28,7 @@ public InheritedBuilderOptionalMutatorDecorator(final GlobalExtensionManagement @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeFromOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); + ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index 06c60f497c..e3c0f6bd84 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -14,7 +14,7 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; -import de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -94,7 +94,7 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later symbolRuleAttributes.stream() - .filter(a -> AccessAsSupplierTyps.shouldBeSupplied(a.getMCType().printType())) + .filter(a -> AccessAsSupplierTypes.shouldHaveSupplier(a.getMCType().printType())) .forEach(a -> a.setMCType(getDecorationHelper().createSupplierTypeOf(a.getMCType()))); symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java new file mode 100644 index 0000000000..c991e0cf29 --- /dev/null +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -0,0 +1,38 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.codegen.cd2java.methods; + +import de.monticore.cdbasis._ast.ASTCDAttribute; + +import java.util.Arrays; + +/** + * Some attributes in symbolrules must be decorated with a supplier, since they might not be known immediatly during the deserialization. + * + * This class contains what those types are + */ +public class AccessAsSupplierTypes { + + /** + * Fully qualified name of the wrapper type used for lazily resolved attributes. + */ + public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; + + private static final String[] SUPPLYLIST = { + "de.monticore.types.check.SymTypeExpression", + "java.util.List", + "java.util.Optional" + }; + + /** + * @param type the fully qualified, printed attribute type + * @return whether an attribute of this type should be wrapped in / accessed via a {@code Supplier} + */ + public static boolean shouldHaveSupplier(String type) { + return Arrays.asList(SUPPLYLIST).contains(type); + } + + public static boolean shouldHaveSupplier(ASTCDAttribute attribute) { + return shouldHaveSupplier(attribute.getMCType().printType()); + } + +} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java deleted file mode 100644 index 871e675df9..0000000000 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java +++ /dev/null @@ -1,22 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.codegen.cd2java.methods; - -import java.util.Arrays; - - -public class AccessAsSupplierTyps { - - public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; - - // TODO also accept non-fully-qualified spellings - public static final String[] SUPPLYLIST = { - "de.monticore.types.check.SymTypeExpression", - "java.util.List", - "java.util.Optional" - }; - - - public static boolean shouldBeSupplied(String t) { - return Arrays.asList(SUPPLYLIST).contains(t); - } -} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java index 1125d19c4a..f14d4298ec 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java @@ -87,7 +87,7 @@ public String getAttributeType(ASTCDAttribute attribute) { if (getDecorationHelper().isSupplier(type)) { // a wrapped list attribute has the shape Supplier> -> unwrap to List before extracting X - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } return getTypeArgumentFromListType(type); } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java index 55378a921c..fc7f1c58ff 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java @@ -51,7 +51,7 @@ protected AbstractCreator> determineMethodDeco // If the type is wrapped (supplier), unwrap for determination ASTMCType type = ast.getMCType(); if (getDecorationHelper().isSupplier(type)) { - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } if (getMCTypeFacade().isBooleanType(type)) { diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java new file mode 100644 index 0000000000..36d5c52511 --- /dev/null +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java @@ -0,0 +1,17 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.codegen.cd2java.methods; + +import java.util.function.Supplier; + +public class __internal__Supplier implements Supplier { + Supplier supplier; + + public __internal__Supplier(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public T get() { + return supplier.get(); + } +} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index 8956a77916..315bda7cad 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -45,7 +45,7 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)) { // The Supplier is hidden from the user. The getter has to expose the unwrapped type (Supplier -> X) - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); templateName = "methods.SupplierGet"; } else { templateName = "methods.Get"; diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index fea7b20524..72d5b971b2 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -5,7 +5,6 @@ import de.monticore.cd4codebasis._ast.ASTCDMethod; import de.monticore.codegen.cd2java.AbstractCreator; import de.monticore.codegen.cd2java.AbstractService; -import de.monticore.codegen.cd2java.DecorationHelper; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; import de.monticore.types.mcbasictypes._ast.ASTMCType; @@ -53,12 +52,12 @@ protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)){ templateName = "methods.opt.SupplierGet4Opt"; - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } else { templateName = "methods.opt.Get4Opt"; } - type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get(); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); String generatedErrorCode = service.getGeneratedErrorCode(ast.getName() + ast.printType()); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName, generatedErrorCode)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java index 41439ff3c7..6f2294a62e 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java @@ -34,7 +34,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { if (getDecorationHelper().isSupplier(ast.getMCType())) { // expose the unwrapped type (Supplier -> X) in the setter parameter; the Supplier stays hidden attribute = ast.deepClone(); - attribute.setMCType(getDecorationHelper().getReferenceTypeFromSupply(attribute.getMCType()).getMCTypeOpt().get()); + attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); templateName = "methods.SupplierSet"; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index 081fcd24b2..464011b828 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -44,12 +44,12 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)){ templateName = "methods.opt.SupplierSet4Opt"; - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } else { templateName = "methods.opt.Set4Opt"; } - type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get().deepClone(); + type = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(type, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName)); diff --git a/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl b/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl index 078cad0d68..a63c8fc1a4 100644 --- a/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl +++ b/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl @@ -27,7 +27,7 @@ ${tc.signature("attributeList", "hasSuperClass")} <#elseif genHelper.isPrimitive(attrType)> result.set${methName}(${genHelper.getPlainGetter(attribute)}()); <#elseif genHelper.isOptional(attribute.getMCType())> - <#assign reference = genHelper.getReferenceTypeFromOptional(attrType)> + <#assign reference = genHelper.getReferenceTypeOfOptional(attrType)> <#assign referenceName = typeName> <#if genHelper.isString(reference) || genHelper.isAttributeOfTypeEnum(attribute)> if (isPresent${methName}()) { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java index e7484e3857..2ab503dfd3 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java @@ -21,11 +21,11 @@ public void setFunctionList(List methodList){ } public List getSuperClassesOnly(){ - return superTypes.get(); + return getSuperTypesList(); } public List getInterfaceList(){ - return superTypes.get(); + return getSuperTypesList(); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java index 09c343dfcb..23a484dc71 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java +++ b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java @@ -9,6 +9,7 @@ import de.monticore.types.mccollectiontypes._ast.*; import de.monticore.types.mcfullgenerictypes.MCFullGenericTypesMill; import de.monticore.types.mcfullgenerictypes._ast.ASTMCWildcardTypeArgument; +import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.types.mcsimplegenerictypes._ast.ASTMCBasicGenericType; import java.util.ArrayList; @@ -248,6 +249,29 @@ public ASTMCArrayType createArrayType(final String name, int dimension) { return createArrayType(this.createQualifiedType(name), dimension); } + /** + * {@code java.util.function.Supplier} types + */ + + public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCTypeArgument inner) { + return createBasicGenericTypeOf("java.util.function.Supplier", inner); + } + + public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCType inner) { + ASTMCTypeArgument arg = MCSimpleGenericTypesMill.mCCustomTypeArgumentBuilder() + .setMCType(inner.deepClone()) + .build(); + return createSupplierTypeOf(arg); + } + + public ASTMCBasicGenericType createSupplierTypeOf(final String name) { + return createSupplierTypeOf(createBasicTypeArgumentOf(name)); + } + + public ASTMCBasicGenericType createSupplierTypeOf(final Class clazz) { + return createSupplierTypeOf(clazz.getName()); + } + /** * primitive types */ From 3982a02932afa3a40fd739adb59f5cee79048b00 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Thu, 10 Sep 2026 10:57:16 +0200 Subject: [PATCH 03/21] use __internal__Supplier --- .../codegen/cd2java/DecorationHelper.java | 13 ++++++---- .../methods/AccessAsSupplierTypes.java | 2 +- .../cd2java/methods/__internal__Supplier.java | 17 ------------- .../main/resources/methods/SupplierSet.ftl | 2 +- .../resources/methods/opt/SupplierSet4Opt.ftl | 2 +- .../methods/opt/SupplierSetAbsent.ftl | 2 +- .../compsymbols/_symboltable/PortSymbol.java | 3 ++- .../java/de/monticore/types/MCTypeFacade.java | 4 ++-- .../symboltable/__internal__Supplier.java | 24 +++++++++++++++++++ 9 files changed, 40 insertions(+), 29 deletions(-) delete mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java create mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index b292019847..e6db0ef556 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -105,12 +105,15 @@ public boolean isOptional(String type) { return "Optional".equals(Names.getSimpleName(type)); } + /** + * Checks whether the type is wrapped by the internal supplier type + */ public boolean isSupplier(String type) { int index = type.indexOf('<'); if (index != -1) { type = type.substring(0, index); } - return "Supplier".equals(Names.getSimpleName(type)); + return Names.getSimpleName(SUPPLIER_TYPE).equals(Names.getSimpleName(type)); } // The ASTMCType overloads intentionally delegate to the String checks above instead of using @@ -196,12 +199,12 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM // the initialization expression that is placed after the '=' of the field declaration String defaultValue; if (!isSupplier) { - defaultValue = inner; + defaultValue = inner; } else if (isList) { // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. - defaultValue = "com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; + defaultValue = "new " + SUPPLIER_TYPE + "<>(com.google.common.base.Suppliers.memoize(() -> " + inner + "))"; } else { - defaultValue = "() -> " + inner; + defaultValue = "new " + SUPPLIER_TYPE + "<>(() -> " + inner + ")"; } glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= " + defaultValue)); } @@ -229,7 +232,7 @@ public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { } /** - * Wraps {@code inner} into {@code Supplier} + * Wraps {@code inner} into the internal supplier type {@code __internal__Supplier} * * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... */ diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java index c991e0cf29..e8b6afaeac 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -15,7 +15,7 @@ public class AccessAsSupplierTypes { /** * Fully qualified name of the wrapper type used for lazily resolved attributes. */ - public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; + public static final String SUPPLIER_TYPE = "de.monticore.symboltable.__internal__Supplier"; private static final String[] SUPPLYLIST = { "de.monticore.types.check.SymTypeExpression", diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java deleted file mode 100644 index 36d5c52511..0000000000 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java +++ /dev/null @@ -1,17 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.codegen.cd2java.methods; - -import java.util.function.Supplier; - -public class __internal__Supplier implements Supplier { - Supplier supplier; - - public __internal__Supplier(Supplier supplier) { - this.supplier = supplier; - } - - @Override - public T get() { - return supplier.get(); - } -} diff --git a/monticore-generator/src/main/resources/methods/SupplierSet.ftl b/monticore-generator/src/main/resources/methods/SupplierSet.ftl index 41e8259e86..32a51f6ba6 100644 --- a/monticore-generator/src/main/resources/methods/SupplierSet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierSet.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = () -> ${attribute.getName()}; +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> ${attribute.getName()}); ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl index 69d9a84eed..b0b48853bc 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute", "nativeAttributeName")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = () -> Optional.ofNullable(${attribute.getName()}); +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.ofNullable(${attribute.getName()})); ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl index 9a899540ca..8a37f755fa 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = () -> Optional.empty(); +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.empty()); ${defineHookPoint("Setter:After")} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java index 1b26b798ac..e100ed0580 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java @@ -34,7 +34,8 @@ protected PortSymbol(String name, } public boolean isTypePresent() { - return this.type != null; + // type is not an optional, so we resolve it here to check if it is null + return super.type.get() != null; } public SymTypeExpression getType() { diff --git a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java index 23a484dc71..f98231098d 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java +++ b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java @@ -250,11 +250,11 @@ public ASTMCArrayType createArrayType(final String name, int dimension) { } /** - * {@code java.util.function.Supplier} types + * {@code de.monticore.symboltable.__internal__Supplier} types. */ public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCTypeArgument inner) { - return createBasicGenericTypeOf("java.util.function.Supplier", inner); + return createBasicGenericTypeOf("de.monticore.symboltable.__internal__Supplier", inner); } public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCType inner) { diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java new file mode 100644 index 0000000000..6d2aa5931e --- /dev/null +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java @@ -0,0 +1,24 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.symboltable; + +import java.util.function.Supplier; + +/** + * Internal marker wrapper used by generated symbol classes for symbolrule attributes whose value + * may not be resolvable yet (see {@code AccessAsSupplierTypes} in the generator). + *

+ * A dedicated type (instead of a plain {@link Supplier}) is required in case someone wants to actually return a supplier + */ +public class __internal__Supplier implements Supplier { + + protected final Supplier supplier; + + public __internal__Supplier(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public T get() { + return supplier.get(); + } +} From 85267450c53c2032a0d79a6fac5dfa4dfe75b265 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Fri, 11 Sep 2026 07:51:11 +0200 Subject: [PATCH 04/21] supplierGet now warn instead if throwing --- .../src/main/resources/methods/SupplierGet.ftl | 2 +- .../src/main/resources/methods/opt/SupplierGet4Opt.ftl | 5 ++--- .../src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/monticore-generator/src/main/resources/methods/SupplierGet.ftl b/monticore-generator/src/main/resources/methods/SupplierGet.ftl index 44470de684..384679bbbe 100644 --- a/monticore-generator/src/main/resources/methods/SupplierGet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierGet.ftl @@ -2,6 +2,6 @@ ${tc.signature("attribute")} var __value = this.${attribute.getName()}.get(); if (__value == null) { - throw new IllegalStateException("Value of '${attribute.getName()}' is not available yet."); +Log.warn("Value of '${attribute.getName()}' is not available yet."); } return __value; diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl index ac245b7d34..42b9353cb4 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl @@ -3,6 +3,5 @@ ${tc.signature("attribute", "naiveAttributeName", "generatedErrorCode")} if (isPresent${naiveAttributeName}()) { return this.${attribute.getName()}.get().get(); } - Log.error("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); - // Normally this statement is not reachable - throw new IllegalStateException(); + Log.warn("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); + return null; diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl index adcb16fcd6..41286f5cf2 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl @@ -1,7 +1,8 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -var optional = this.${attribute.getName()}.get(); +var optional = this.${attribute.getName()}.get(); if (optional == null){ - throw new IllegalStateException("supplier for ${attribute.getName()} is null"); + Log.warn("supplier for ${attribute.getName()} is null"); + return false; } return optional.isPresent(); From bd04066a35247a56c044fca1c2a20375a46cd682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 11 Sep 2026 11:12:03 +0200 Subject: [PATCH 05/21] spike through SymTypeOfObject now uses supplier --- .../types/check/SymTypeExpressionFactory.java | 17 +++------------ .../types/check/SymTypeOfObject.java | 18 ++++++++++------ .../types/check/SymTypeOfObjectDeSer.java | 5 +---- .../symboltable/SimpleSymbolSupplier.java | 21 +++++++++++++++++++ 4 files changed, 37 insertions(+), 24 deletions(-) create mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index 8cd179d1f8..77bbd4d303 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -4,12 +4,8 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import de.monticore.symbols.basicsymbols.BasicSymbolsMill; -import de.monticore.symbols.basicsymbols._symboltable.FunctionSymbol; -import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; -import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; -import de.monticore.symbols.basicsymbols._util.IBasicSymbolsTypeDispatcher; +import de.monticore.symbols.basicsymbols._symboltable.*; +import de.monticore.symboltable.ISymbolSupplier; import de.se_rwth.commons.logging.Log; import java.util.ArrayList; @@ -135,15 +131,8 @@ public static SymTypeOfObject createTypeObject(TypeSymbol typeSymbol) { return new SymTypeOfObject(typeSymbol); } - /** - * @deprecated did hide the usage of surrogate, and leads to questionable code - * consider using - * {@link de.monticore.types3.util.WithinScopeBasicSymbolsResolver#resolveType(IBasicSymbolsScope, String)}, - * of creating a Surrogate explicitly (only if required) - */ - @Deprecated(forRemoval = true) public static SymTypeOfObject createTypeObject(String name, IBasicSymbolsScope enclosingScope) { - return createTypeObjectViaSurrogate(name, enclosingScope); + return new SymTypeOfObject(ISymbolSupplier.memoize(new TypeSymbolSupplier(name, enclosingScope))); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java index 1bd0d40b18..958c359a76 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java @@ -3,8 +3,9 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symboltable.ISymbolSupplier; +import de.monticore.symboltable.SimpleSymbolSupplier; import de.monticore.types3.ISymTypeVisitor; -import de.se_rwth.commons.logging.Log; /** * An objectType is a full qualified class name. @@ -13,13 +14,18 @@ */ public class SymTypeOfObject extends SymTypeExpression { - protected TypeSymbol typeSymbol; + protected ISymbolSupplier typeSymbol; /** * Constructor: with a TypeSymbolSurrogate that contains the name and enclosingScope */ public SymTypeOfObject(TypeSymbol typeSymbol) { + Preconditions.checkNotNull(typeSymbol); + this.typeSymbol = new SimpleSymbolSupplier<>(typeSymbol); + } + + public SymTypeOfObject(ISymbolSupplier typeSymbol) { Preconditions.checkNotNull(typeSymbol); this.typeSymbol = typeSymbol; } @@ -27,12 +33,12 @@ public SymTypeOfObject(TypeSymbol typeSymbol) @Override public boolean hasTypeInfo() { // should allways be true - return typeSymbol != null; + return typeSymbol.get().isPresent(); } @Override public TypeSymbol getTypeInfo() { - return typeSymbol; + return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())); } /** @@ -42,7 +48,7 @@ public TypeSymbol getTypeInfo() { */ @Deprecated(forRemoval = true) public String getObjName() { - return typeSymbol.getFullName(); + return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).getFullName(); } /** @@ -50,7 +56,7 @@ public String getObjName() { */ @Deprecated(forRemoval = true) public void setObjName(String objname) { - this.typeSymbol.setName(objname); + this.typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).setName(objname); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java index e9b1406717..6e72677c51 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java @@ -3,7 +3,6 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -43,9 +42,7 @@ public SymTypeOfObject deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - TypeSymbolSurrogate typeSym = new TypeSymbolSurrogate(objName); - typeSym.setEnclosingScope(enclosingScope); - return SymTypeExpressionFactory.createTypeObject(typeSym); + return SymTypeExpressionFactory.createTypeObject(objName, enclosingScope); } Log.error("0x823F4 Internal error: Cannot load \"" + serialized + "\" as SymTypeOfObject!"); diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java new file mode 100644 index 0000000000..4df09c6b33 --- /dev/null +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java @@ -0,0 +1,21 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.symboltable; + +import com.google.common.base.Preconditions; + +import java.util.Optional; + +public class SimpleSymbolSupplier implements ISymbolSupplier { + + private final T value; + + public SimpleSymbolSupplier(T value){ + Preconditions.checkNotNull(value); + this.value = value; + } + + @Override + public Optional get() { + return Optional.of(value); + } +} From 91f492d1e7afa65e91c8759eb003d6e886e84de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 11 Sep 2026 11:39:47 +0200 Subject: [PATCH 06/21] Revert "spike through SymTypeOfObject now uses supplier" This reverts commit bd04066a35247a56c044fca1c2a20375a46cd682. --- .../types/check/SymTypeExpressionFactory.java | 17 ++++++++++++--- .../types/check/SymTypeOfObject.java | 18 ++++++---------- .../types/check/SymTypeOfObjectDeSer.java | 5 ++++- .../symboltable/SimpleSymbolSupplier.java | 21 ------------------- 4 files changed, 24 insertions(+), 37 deletions(-) delete mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index 77bbd4d303..8cd179d1f8 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -4,8 +4,12 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import de.monticore.symbols.basicsymbols.BasicSymbolsMill; -import de.monticore.symbols.basicsymbols._symboltable.*; -import de.monticore.symboltable.ISymbolSupplier; +import de.monticore.symbols.basicsymbols._symboltable.FunctionSymbol; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; +import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; +import de.monticore.symbols.basicsymbols._util.IBasicSymbolsTypeDispatcher; import de.se_rwth.commons.logging.Log; import java.util.ArrayList; @@ -131,8 +135,15 @@ public static SymTypeOfObject createTypeObject(TypeSymbol typeSymbol) { return new SymTypeOfObject(typeSymbol); } + /** + * @deprecated did hide the usage of surrogate, and leads to questionable code + * consider using + * {@link de.monticore.types3.util.WithinScopeBasicSymbolsResolver#resolveType(IBasicSymbolsScope, String)}, + * of creating a Surrogate explicitly (only if required) + */ + @Deprecated(forRemoval = true) public static SymTypeOfObject createTypeObject(String name, IBasicSymbolsScope enclosingScope) { - return new SymTypeOfObject(ISymbolSupplier.memoize(new TypeSymbolSupplier(name, enclosingScope))); + return createTypeObjectViaSurrogate(name, enclosingScope); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java index 958c359a76..1bd0d40b18 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java @@ -3,9 +3,8 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symboltable.ISymbolSupplier; -import de.monticore.symboltable.SimpleSymbolSupplier; import de.monticore.types3.ISymTypeVisitor; +import de.se_rwth.commons.logging.Log; /** * An objectType is a full qualified class name. @@ -14,18 +13,13 @@ */ public class SymTypeOfObject extends SymTypeExpression { - protected ISymbolSupplier typeSymbol; + protected TypeSymbol typeSymbol; /** * Constructor: with a TypeSymbolSurrogate that contains the name and enclosingScope */ public SymTypeOfObject(TypeSymbol typeSymbol) { - Preconditions.checkNotNull(typeSymbol); - this.typeSymbol = new SimpleSymbolSupplier<>(typeSymbol); - } - - public SymTypeOfObject(ISymbolSupplier typeSymbol) { Preconditions.checkNotNull(typeSymbol); this.typeSymbol = typeSymbol; } @@ -33,12 +27,12 @@ public SymTypeOfObject(ISymbolSupplier typeSymbol) { @Override public boolean hasTypeInfo() { // should allways be true - return typeSymbol.get().isPresent(); + return typeSymbol != null; } @Override public TypeSymbol getTypeInfo() { - return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())); + return typeSymbol; } /** @@ -48,7 +42,7 @@ public TypeSymbol getTypeInfo() { */ @Deprecated(forRemoval = true) public String getObjName() { - return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).getFullName(); + return typeSymbol.getFullName(); } /** @@ -56,7 +50,7 @@ public String getObjName() { */ @Deprecated(forRemoval = true) public void setObjName(String objname) { - this.typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).setName(objname); + this.typeSymbol.setName(objname); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java index 6e72677c51..e9b1406717 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java @@ -3,6 +3,7 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -42,7 +43,9 @@ public SymTypeOfObject deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - return SymTypeExpressionFactory.createTypeObject(objName, enclosingScope); + TypeSymbolSurrogate typeSym = new TypeSymbolSurrogate(objName); + typeSym.setEnclosingScope(enclosingScope); + return SymTypeExpressionFactory.createTypeObject(typeSym); } Log.error("0x823F4 Internal error: Cannot load \"" + serialized + "\" as SymTypeOfObject!"); diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java deleted file mode 100644 index 4df09c6b33..0000000000 --- a/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java +++ /dev/null @@ -1,21 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symboltable; - -import com.google.common.base.Preconditions; - -import java.util.Optional; - -public class SimpleSymbolSupplier implements ISymbolSupplier { - - private final T value; - - public SimpleSymbolSupplier(T value){ - Preconditions.checkNotNull(value); - this.value = value; - } - - @Override - public Optional get() { - return Optional.of(value); - } -} From 437fe930ed3a455f50762926eb87cb69a9c556b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 4 Sep 2026 20:03:51 +0200 Subject: [PATCH 07/21] SymTypeExpression and wrappers return a supplier in case the symbol can not be resolved immediatly --- .../codegen/cd2java/DecorationHelper.java | 68 +++++++++++++++++-- .../_symboltable/symbol/SymbolDecorator.java | 7 ++ .../cd2java/methods/AccessAsSupplierTyps.java | 22 ++++++ .../cd2java/methods/ListMethodDecorator.java | 8 ++- .../methods/SpecificMethodDecorator.java | 13 +++- .../accessor/ListAccessorDecorator.java | 10 ++- .../accessor/MandatoryAccessorDecorator.java | 12 +++- .../accessor/OptionalAccessorDecorator.java | 24 ++++++- .../methods/mutator/ListMutatorDecorator.java | 10 ++- .../mutator/MandatoryMutatorDecorator.java | 15 +++- .../mutator/OptionalMutatorDecorator.java | 26 +++++-- .../main/resources/methods/SupplierGet.ftl | 7 ++ .../main/resources/methods/SupplierSet.ftl | 5 ++ .../resources/methods/opt/SupplierGet4Opt.ftl | 8 +++ .../methods/opt/SupplierIsPresent4Opt.ftl | 7 ++ .../resources/methods/opt/SupplierSet4Opt.ftl | 5 ++ .../methods/opt/SupplierSetAbsent.ftl | 5 ++ .../basicsymbols/_symboltable/TypeSymbol.java | 4 +- .../_symboltable/VariableSymbol.java | 5 +- .../ComponentType2TypeSymbolAdapter.java | 4 +- .../compsymbols/_symboltable/PortSymbol.java | 9 +-- .../oosymbols/_symboltable/MethodSymbol.java | 2 +- .../oosymbols/_symboltable/OOTypeSymbol.java | 4 +- .../mc/feature/symbolrules/SymbolruleTest.mc4 | 2 +- 24 files changed, 245 insertions(+), 37 deletions(-) create mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java create mode 100644 monticore-generator/src/main/resources/methods/SupplierGet.ftl create mode 100644 monticore-generator/src/main/resources/methods/SupplierSet.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl create mode 100644 monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 69365678d7..4efabf8f14 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -13,6 +13,9 @@ import de.monticore.generating.templateengine.StringHookPoint; import de.monticore.symboltable.ISymbol; import de.monticore.types.MCBasicTypesHelper; +import de.monticore.types.MCTypeFacade; +import de.monticore.types.mccollectiontypes._ast.ASTMCListType; +import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.types.mcbasictypes._ast.ASTMCPrimitiveType; import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType; @@ -31,6 +34,7 @@ import static de.monticore.cd.codegen.CD2JavaTemplates.VALUE; import static de.monticore.codegen.cd2java._ast.ast_class.ASTConstants.AST_PREFIX; +import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps.SUPPLIER_TYPE; public class DecorationHelper extends MCBasicTypesHelper { @@ -67,7 +71,7 @@ public boolean isAstNode(ASTCDAttribute attr) { } public boolean isSimpleAstNode(ASTCDAttribute attr) { - return !isOptional(attr.getMCType()) && !isListType(attr.printType()) && isAstNode(attr); + return !isOptional(attr.getMCType()) && !isList(attr.getMCType()) && isAstNode(attr); } public boolean isOptionalAstNode(ASTCDAttribute attr) { @@ -75,7 +79,7 @@ public boolean isOptionalAstNode(ASTCDAttribute attr) { } public boolean isListAstNode(ASTCDAttribute attribute) { - return isListType(attribute.printType()) && isAstNode(attribute); + return isList(attribute.getMCType()) && isAstNode(attribute); } public boolean isListType(String type) { @@ -113,6 +117,25 @@ public boolean isOptional(ASTMCType type) { return false; } + public boolean isList(ASTMCType type) { + if (type instanceof ASTMCListType) { + return true; + } else if (type instanceof ASTMCGenericType) { + String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); + return "List".equals(Names.getSimpleName(simpleType)); + } + return false; + } + + public boolean isSupplier(ASTMCType type) { + if (type instanceof ASTMCGenericType) { + String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); + return "Supplier".equals(Names.getSimpleName(simpleType)); + } + return false; + } + + public boolean isString(String type) { return "String".equals(type) || "java.lang.String".equals(type); } @@ -159,12 +182,34 @@ public String getSimpleNativeType(String nativeAttributeType) { * important for Optional and List types */ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionManagement glex) { - if (isListType(attribute.printType())) { - glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= new java.util.ArrayList<>()")); + // For a wrapped attribute (Supplier) the default is derived from the unwrapped type X. + ASTMCType type = attribute.getMCType(); + boolean isSupplier = isSupplier(type); + if (isSupplier) { + type = getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } - } else if (isOptional(attribute.getMCType())) { - glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= Optional.empty()")); + String inner; + if (isList(type)) { + inner = "new java.util.ArrayList<>()"; + } else if (isOptional(type)) { + inner = "Optional.empty()"; + } else if (isSupplier) { + inner = "null"; + } else { + return; } + + String defaultValue; + if (!isSupplier) { + defaultValue = "= " + inner; + } else if (isList(type)) { + // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. + defaultValue = "= com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; + } else { + defaultValue = "= () -> " + inner; + } + glex.replaceTemplate(VALUE, attribute, new StringHookPoint(defaultValue)); } /** @@ -184,6 +229,17 @@ public ASTMCTypeArgument getReferenceTypeFromOptional(ASTMCType type) { return ((ASTMCGenericType) type).getMCTypeArgumentList().getFirst(); } + public ASTMCTypeArgument getReferenceTypeFromSupply(ASTMCType type) { + Preconditions.checkArgument(isSupplier(type)); + return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); + } + + public ASTMCType createSupplierTypeOf(ASTMCType inner) { + ASTMCTypeArgument arg = MCSimpleGenericTypesMill + .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); + return MCTypeFacade.getInstance().createBasicGenericTypeOf(SUPPLIER_TYPE, arg); + } + /** * methods only used in templates */ diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index bbde906e2d..3bcd5fb9aa 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -14,6 +14,7 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -90,6 +91,12 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { .filter(attr -> !symbolTableService.isInheritedAttribute(attr)) .map(ASTCDAttribute::deepClone) .collect(Collectors.toList()); + + // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later + symbolRuleAttributes.stream() + .filter(a -> AccessAsSupplierTyps.shouldBeSupplied(a.getMCType().printType())) + .forEach(a -> a.setMCType(getDecorationHelper().createSupplierTypeOf(a.getMCType()))); + symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); List symbolRuleAttributeMethods = symbolRuleAttributes .stream() diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java new file mode 100644 index 0000000000..871e675df9 --- /dev/null +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java @@ -0,0 +1,22 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.codegen.cd2java.methods; + +import java.util.Arrays; + + +public class AccessAsSupplierTyps { + + public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; + + // TODO also accept non-fully-qualified spellings + public static final String[] SUPPLYLIST = { + "de.monticore.types.check.SymTypeExpression", + "java.util.List", + "java.util.Optional" + }; + + + public static boolean shouldBeSupplied(String t) { + return Arrays.asList(SUPPLYLIST).contains(t); + } +} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java index e193305c0d..1125d19c4a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java @@ -83,6 +83,12 @@ public String getCapitalizedAttributeNameWithS(ASTCDAttribute attribute) { } public String getAttributeType(ASTCDAttribute attribute) { - return getTypeArgumentFromListType(attribute.getMCType()); + ASTMCType type = attribute.getMCType(); + + if (getDecorationHelper().isSupplier(type)) { + // a wrapped list attribute has the shape Supplier> -> unwrap to List before extracting X + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } + return getTypeArgumentFromListType(type); } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java index a88d4507f7..55378a921c 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java @@ -5,6 +5,7 @@ import de.monticore.cd4codebasis._ast.ASTCDMethod; import de.monticore.codegen.cd2java.AbstractCreator; import de.monticore.generating.templateengine.GlobalExtensionManagement; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import java.util.List; @@ -47,11 +48,17 @@ public List decorate(final ASTCDAttribute ast) { } protected AbstractCreator> determineMethodDecoratorStrategy(final ASTCDAttribute ast) { - if (getMCTypeFacade().isBooleanType(ast.getMCType())) { + // If the type is wrapped (supplier), unwrap for determination + ASTMCType type = ast.getMCType(); + if (getDecorationHelper().isSupplier(type)) { + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } + + if (getMCTypeFacade().isBooleanType(type)) { return mandatoryMethodDecorator; - } else if (getDecorationHelper().isListType(ast.printType())) { + } else if (getDecorationHelper().isList(type)) { return listMethodDecorator; - } else if (getDecorationHelper().isOptional(ast.getMCType())) { + } else if (getDecorationHelper().isOptional(type)) { return optionalMethodDecorator; } return mandatoryMethodDecorator; diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java index 2c7004272d..302dcb415b 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java @@ -49,7 +49,15 @@ public List decorate(ASTCDAttribute ast) { protected ASTCDMethod createGetListMethod(ASTCDAttribute ast) { String signature = String.format(GET_LIST, attributeType, capitalizedAttributeNameWithOutS); ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature); - this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Get", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + templateName = "methods.SupplierGet"; + } else { + templateName = "methods.Get"; + } + + this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint(templateName, ast)); return getList; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index 9c2de169db..dfb76d3da8 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -41,8 +41,18 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { } String name = String.format(getterPrefix, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); ASTMCType type = ast.getMCType().deepClone(); + + String templateName; + if (getDecorationHelper().isSupplier(type)) { + // The Supplier is hidden from the user. The getter has to expose the unwrapped type (Supplier -> X) + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + templateName = "methods.SupplierGet"; + } else { + templateName = "methods.Get"; + } + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.Get", ast)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index 508cdd9deb..95ad7a9251 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -47,17 +47,35 @@ protected String getNaiveAttributeName(ASTCDAttribute astcdAttribute) { protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String name = String.format(GET, naiveAttributeName); - ASTMCType type = getDecorationHelper().getReferenceTypeFromOptional(ast.getMCType().deepClone()).getMCTypeOpt().get(); + + ASTMCType type = ast.getMCType().deepClone(); + String templateName; + if (getDecorationHelper().isSupplier(type)){ + templateName = "methods.opt.SupplierGet4Opt"; + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } else { + templateName = "methods.opt.Get4Opt"; + } + + type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get(); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); String generatedErrorCode = service.getGeneratedErrorCode(ast.getName() + ast.printType()); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.Get4Opt", ast, naiveAttributeName, generatedErrorCode)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName, generatedErrorCode)); return method; } protected ASTCDMethod createIsPresentMethod(final ASTCDAttribute ast) { String name = String.format(IS_PRESENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), getMCTypeFacade().createBooleanType(), name); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.IsPresent4Opt", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())){ + templateName = "methods.opt.SupplierIsPresent4Opt"; + } else { + templateName = "methods.opt.IsPresent4Opt"; + } + + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java index 603a983390..ac932899ff 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java @@ -44,7 +44,15 @@ public List decorate(ASTCDAttribute ast) { protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { String signature = String.format(SET_LIST, capitalizedAttributeNameWithOutS, attributeType, ast.getName()); ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature); - this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint("methods.Set", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + templateName = "methods.SupplierSet"; + } else { + templateName = "methods.Set"; + } + + this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint(templateName, ast)); return getList; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java index 903fdd5c48..75678f35d1 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java @@ -29,9 +29,18 @@ public List decorate(final ASTCDAttribute ast) { } protected ASTCDMethod createSetter(final ASTCDAttribute ast) { - String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); - ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, this.getCDParameterFacade().createParameters(ast)); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.Set", ast)); + ASTCDAttribute attribute = ast; + String templateName = "methods.Set"; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + // expose the unwrapped type (Supplier -> X) in the setter parameter; the Supplier stays hidden + attribute = ast.deepClone(); + attribute.setMCType(getDecorationHelper().getReferenceTypeFromSupply(attribute.getMCType()).getMCTypeOpt().get()); + templateName = "methods.SupplierSet"; + } + + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index a11baf943a..081fcd24b2 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -39,17 +39,35 @@ public List decorate(final ASTCDAttribute ast) { protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeFromOptional(ast.getMCType()).getMCTypeOpt().get().deepClone(); - ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, ast.getName()); + + ASTMCType type = ast.getMCType().deepClone(); + String templateName; + if (getDecorationHelper().isSupplier(type)){ + templateName = "methods.opt.SupplierSet4Opt"; + type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + } else { + templateName = "methods.opt.Set4Opt"; + } + + type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get().deepClone(); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(type, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.Set4Opt", ast, naiveAttributeName)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName)); return method; } protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute ast) { String name = String.format(SET_ABSENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.opt.SetAbsent", ast)); + + String templateName; + if (getDecorationHelper().isSupplier(ast.getMCType())){ + templateName = "methods.opt.SupplierSetAbsent"; + } else { + templateName = "methods.opt.SetAbsent"; + } + + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } } diff --git a/monticore-generator/src/main/resources/methods/SupplierGet.ftl b/monticore-generator/src/main/resources/methods/SupplierGet.ftl new file mode 100644 index 0000000000..44470de684 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/SupplierGet.ftl @@ -0,0 +1,7 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +var __value = this.${attribute.getName()}.get(); +if (__value == null) { + throw new IllegalStateException("Value of '${attribute.getName()}' is not available yet."); +} +return __value; diff --git a/monticore-generator/src/main/resources/methods/SupplierSet.ftl b/monticore-generator/src/main/resources/methods/SupplierSet.ftl new file mode 100644 index 0000000000..41e8259e86 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/SupplierSet.ftl @@ -0,0 +1,5 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = () -> ${attribute.getName()}; +${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl new file mode 100644 index 0000000000..ac245b7d34 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl @@ -0,0 +1,8 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute", "naiveAttributeName", "generatedErrorCode")} + if (isPresent${naiveAttributeName}()) { + return this.${attribute.getName()}.get().get(); + } + Log.error("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); + // Normally this statement is not reachable + throw new IllegalStateException(); diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl new file mode 100644 index 0000000000..adcb16fcd6 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl @@ -0,0 +1,7 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +var optional = this.${attribute.getName()}.get(); +if (optional == null){ + throw new IllegalStateException("supplier for ${attribute.getName()} is null"); +} +return optional.isPresent(); diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl new file mode 100644 index 0000000000..69d9a84eed --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl @@ -0,0 +1,5 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute", "nativeAttributeName")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = () -> Optional.ofNullable(${attribute.getName()}); +${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl new file mode 100644 index 0000000000..9a899540ca --- /dev/null +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl @@ -0,0 +1,5 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = () -> Optional.empty(); +${defineHookPoint("Setter:After")} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java index 78af208b98..c11850a628 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java @@ -21,11 +21,11 @@ public void setFunctionList(List methodList){ } public List getSuperClassesOnly(){ - return superTypes; + return superTypes.get(); } public List getInterfaceList(){ - return superTypes; + return superTypes.get(); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java index 328818c74a..3fa23d4911 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java @@ -22,8 +22,9 @@ public VariableSymbol deepClone(){ if(isPresentAstNode()) { clone.setAstNode(this.getAstNode()); } - if(type!=null){ - clone.setType(type.deepClone()); + SymTypeExpression t = getType(); + if(t!=null){ + clone.setType(t.deepClone()); } return clone; } diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java index 0458e3960b..70578ae6d9 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentType2TypeSymbolAdapter.java @@ -20,7 +20,7 @@ public ComponentType2TypeSymbolAdapter(@NonNull ComponentTypeSymbol adaptee) { this.adaptee = adaptee; this.accessModifier = BasicAccessModifier.PUBLIC; this.spannedScope = adaptee.getSpannedScope(); - this.superTypes = adaptee.getSuperComponentsList().stream().map(c -> { + setSuperTypesList(adaptee.getSuperComponentsList().stream().map(c -> { if (!c.isGenericComponentType()) { return SymTypeExpressionFactory.createTypeObject(new ComponentType2TypeSymbolAdapter(c.getTypeInfo())); } else { @@ -28,7 +28,7 @@ public ComponentType2TypeSymbolAdapter(@NonNull ComponentTypeSymbol adaptee) { new ComponentType2TypeSymbolAdapter(c.getTypeInfo()), c.asGenericComponentType().getTypeBindingsAsList() ); } - }).collect(Collectors.toList()); + }).collect(Collectors.toList())); } public ComponentTypeSymbol getAdaptee() { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java index f2066aa0dd..1b26b798ac 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java @@ -27,7 +27,7 @@ protected PortSymbol(String name, SymTypeExpression type, Timing timing) { super(name); - this.type = type; + setType(type); this.timing = timing; this.incoming = incoming; this.outgoing = outgoing; @@ -38,13 +38,14 @@ public boolean isTypePresent() { } public SymTypeExpression getType() { - Preconditions.checkState(this.type != null); - return this.type; + SymTypeExpression t = super.getType(); + Preconditions.checkState(t != null); + return t; } public void setType(@NonNull SymTypeExpression type) { Preconditions.checkNotNull(type); - this.type = type; + super.setType(type); } public TypeSymbol getTypeInfo() { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java index f9809f094b..ae7afb1d41 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java @@ -18,7 +18,7 @@ public MethodSymbol(String name) { */ public MethodSymbol deepClone() { MethodSymbol clone = new MethodSymbol(name); - clone.setType(this.type.deepClone()); + clone.setType(getType().deepClone()); clone.setEnclosingScope(this.enclosingScope); clone.setFullName(this.fullName); clone.setIsConstructor(this.isConstructor); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java index 4aa74d6011..f22e55eb6c 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/OOTypeSymbol.java @@ -99,7 +99,7 @@ public SymTypeExpression getSuperClass() { public List getSuperClassesOnly() { List normalSuperTypes = super.getSuperClassesOnly().stream() .filter(type -> !(type.getTypeInfo() instanceof OOTypeSymbol)).collect(Collectors.toList()); - List oOSuperTypes = superTypes.stream() + List oOSuperTypes = getSuperTypesList().stream() .filter(type -> type.getTypeInfo() instanceof OOTypeSymbol) .filter(type -> ((OOTypeSymbol) type.getTypeInfo()).isIsClass()) .toList(); @@ -109,7 +109,7 @@ public List getSuperClassesOnly() { @Override public List getInterfaceList() { - return superTypes.stream() + return getSuperTypesList().stream() .filter(type -> type.getTypeInfo() instanceof OOTypeSymbol) .filter(type -> ((OOTypeSymbol) type.getTypeInfo()).isIsInterface()) .collect(Collectors.toList()); diff --git a/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 b/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 index 6b19ce2ceb..79ae74bcf8 100644 --- a/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 +++ b/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 @@ -22,7 +22,7 @@ grammar SymbolruleTest extends de.monticore.MCBasics, de.monticore.symbols.Basic symbolrule ITest = superTypes:de.monticore.types.check.SymTypeExpression* method public de.monticore.types.check.SymTypeExpression getByName(String name){ java.util.Optional expr = Optional.empty(); - for(de.monticore.types.check.SymTypeExpression symType:superTypes){ + for(de.monticore.types.check.SymTypeExpression symType:getSuperTypesList()){ if(symType.print().equals(name)){ expr = Optional.of(symType); } From 8f29bd215f4101f83c53754f968cd55229e969d6 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Thu, 10 Sep 2026 09:53:03 +0200 Subject: [PATCH 08/21] PR feedback --- .../codegen/cd2java/DecorationHelper.java | 73 +++++++++---------- ...erencedDefinitionOptAccessorDecorator.java | 2 +- .../BuilderOptionalMutatorDecorator.java | 2 +- ...eritedBuilderOptionalMutatorDecorator.java | 2 +- .../_symboltable/symbol/SymbolDecorator.java | 4 +- .../methods/AccessAsSupplierTypes.java | 38 ++++++++++ .../cd2java/methods/AccessAsSupplierTyps.java | 22 ------ .../cd2java/methods/ListMethodDecorator.java | 2 +- .../methods/SpecificMethodDecorator.java | 2 +- .../cd2java/methods/__internal__Supplier.java | 17 +++++ .../accessor/MandatoryAccessorDecorator.java | 2 +- .../accessor/OptionalAccessorDecorator.java | 4 +- .../mutator/MandatoryMutatorDecorator.java | 2 +- .../mutator/OptionalMutatorDecorator.java | 4 +- .../data/DeepCloneWithParameters.ftl | 2 +- .../basicsymbols/_symboltable/TypeSymbol.java | 4 +- .../java/de/monticore/types/MCTypeFacade.java | 24 ++++++ 17 files changed, 131 insertions(+), 75 deletions(-) create mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java delete mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java create mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 4efabf8f14..97184a25d4 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -14,13 +14,11 @@ import de.monticore.symboltable.ISymbol; import de.monticore.types.MCBasicTypesHelper; import de.monticore.types.MCTypeFacade; -import de.monticore.types.mccollectiontypes._ast.ASTMCListType; -import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.types.mcbasictypes._ast.ASTMCPrimitiveType; import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType; -import de.monticore.types.mccollectiontypes._ast.ASTMCOptionalType; import de.monticore.types.mccollectiontypes._ast.ASTMCTypeArgument; +import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.umlmodifier._ast.ASTModifier; import de.monticore.umlstereotype._ast.ASTStereoValue; import de.monticore.umlstereotype._ast.ASTStereotype; @@ -34,7 +32,7 @@ import static de.monticore.cd.codegen.CD2JavaTemplates.VALUE; import static de.monticore.codegen.cd2java._ast.ast_class.ASTConstants.AST_PREFIX; -import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps.SUPPLIER_TYPE; +import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes.SUPPLIER_TYPE; public class DecorationHelper extends MCBasicTypesHelper { @@ -104,35 +102,29 @@ public boolean isOptional(String type) { if (index != -1) { type = type.substring(0, index); } - return "Optional".equals(type) || "java.lang.Optional".equals(type); + return "Optional".equals(Names.getSimpleName(type)); } - public boolean isOptional(ASTMCType type) { - if (type instanceof ASTMCOptionalType) { - return true; - } else if (type instanceof ASTMCGenericType) { - String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); - return "Optional".equals(Names.getSimpleName(simpleType)); + public boolean isSupplier(String type) { + int index = type.indexOf('<'); + if (index != -1) { + type = type.substring(0, index); } - return false; + return "Supplier".equals(Names.getSimpleName(type)); + } + + // The ASTMCType overloads intentionally delegate to the String checks above instead of using + // instanceof: a single implementation, and no reliance on the concrete AST node (see PR #372 review). + public boolean isOptional(ASTMCType type) { + return isOptional(type.printType()); } public boolean isList(ASTMCType type) { - if (type instanceof ASTMCListType) { - return true; - } else if (type instanceof ASTMCGenericType) { - String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); - return "List".equals(Names.getSimpleName(simpleType)); - } - return false; + return isListType(type.printType()); } public boolean isSupplier(ASTMCType type) { - if (type instanceof ASTMCGenericType) { - String simpleType = ((ASTMCGenericType) type).printWithoutTypeArguments(); - return "Supplier".equals(Names.getSimpleName(simpleType)); - } - return false; + return isSupplier(type.printType()); } @@ -186,11 +178,12 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM ASTMCType type = attribute.getMCType(); boolean isSupplier = isSupplier(type); if (isSupplier) { - type = getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } + boolean isList = isList(type); String inner; - if (isList(type)) { + if (isList) { inner = "new java.util.ArrayList<>()"; } else if (isOptional(type)) { inner = "Optional.empty()"; @@ -200,16 +193,17 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM return; } + // the initialization expression that is placed after the '=' of the field declaration String defaultValue; - if (!isSupplier) { - defaultValue = "= " + inner; - } else if (isList(type)) { - // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. - defaultValue = "= com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; - } else { - defaultValue = "= () -> " + inner; - } - glex.replaceTemplate(VALUE, attribute, new StringHookPoint(defaultValue)); + if (!isSupplier) { + defaultValue = inner; + } else if (isList) { + // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. + defaultValue = "com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; + } else { + defaultValue = "() -> " + inner; + } + glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= " + defaultValue)); } /** @@ -224,16 +218,21 @@ public String getNativeAttributeName(String attributeName) { return attributeName.substring(JavaNamesHelper.PREFIX_WHEN_WORD_IS_RESERVED.length()); } - public ASTMCTypeArgument getReferenceTypeFromOptional(ASTMCType type) { + public ASTMCTypeArgument getReferenceTypeOfOptional(ASTMCType type) { Preconditions.checkArgument(isOptional(type)); return ((ASTMCGenericType) type).getMCTypeArgumentList().getFirst(); } - public ASTMCTypeArgument getReferenceTypeFromSupply(ASTMCType type) { + public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { Preconditions.checkArgument(isSupplier(type)); return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); } + /** + * Wraps {@code inner} into {@code Supplier} + * + * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... + */ public ASTMCType createSupplierTypeOf(ASTMCType inner) { ASTMCTypeArgument arg = MCSimpleGenericTypesMill .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java index f59b247c53..077b089df6 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/ast_class/reference/definition/methoddecorator/ReferencedDefinitionOptAccessorDecorator.java @@ -43,7 +43,7 @@ protected String getNaiveAttributeName(ASTCDAttribute astcdAttribute) { @Override protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String name = String.format(GET, StringUtils.capitalize(naiveAttributeName)); - ASTMCType type = getDecorationHelper().getReferenceTypeFromOptional(ast.getMCType().deepClone()).getMCTypeOpt().get(); + ASTMCType type = getDecorationHelper().getReferenceTypeOfOptional(ast.getMCType().deepClone()).getMCTypeOpt().get(); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); String referencedSymbolType = symbolTableService.getReferencedSymbolTypeName(ast); String attributeName = this.getDecorationHelper().getNativeAttributeName(ast.getName()); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java index 58a7d8592e..147a826c44 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java @@ -30,7 +30,7 @@ public BuilderOptionalMutatorDecorator(final GlobalExtensionManagement glex, @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeFromOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); + ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java index 70d14d4f7e..b6df5bc534 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java @@ -28,7 +28,7 @@ public InheritedBuilderOptionalMutatorDecorator(final GlobalExtensionManagement @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeFromOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); + ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index 3bcd5fb9aa..9a09e793fb 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -14,7 +14,7 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; -import de.monticore.codegen.cd2java.methods.AccessAsSupplierTyps; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -94,7 +94,7 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later symbolRuleAttributes.stream() - .filter(a -> AccessAsSupplierTyps.shouldBeSupplied(a.getMCType().printType())) + .filter(a -> AccessAsSupplierTypes.shouldHaveSupplier(a.getMCType().printType())) .forEach(a -> a.setMCType(getDecorationHelper().createSupplierTypeOf(a.getMCType()))); symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java new file mode 100644 index 0000000000..c991e0cf29 --- /dev/null +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -0,0 +1,38 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.codegen.cd2java.methods; + +import de.monticore.cdbasis._ast.ASTCDAttribute; + +import java.util.Arrays; + +/** + * Some attributes in symbolrules must be decorated with a supplier, since they might not be known immediatly during the deserialization. + * + * This class contains what those types are + */ +public class AccessAsSupplierTypes { + + /** + * Fully qualified name of the wrapper type used for lazily resolved attributes. + */ + public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; + + private static final String[] SUPPLYLIST = { + "de.monticore.types.check.SymTypeExpression", + "java.util.List", + "java.util.Optional" + }; + + /** + * @param type the fully qualified, printed attribute type + * @return whether an attribute of this type should be wrapped in / accessed via a {@code Supplier} + */ + public static boolean shouldHaveSupplier(String type) { + return Arrays.asList(SUPPLYLIST).contains(type); + } + + public static boolean shouldHaveSupplier(ASTCDAttribute attribute) { + return shouldHaveSupplier(attribute.getMCType().printType()); + } + +} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java deleted file mode 100644 index 871e675df9..0000000000 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTyps.java +++ /dev/null @@ -1,22 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.codegen.cd2java.methods; - -import java.util.Arrays; - - -public class AccessAsSupplierTyps { - - public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; - - // TODO also accept non-fully-qualified spellings - public static final String[] SUPPLYLIST = { - "de.monticore.types.check.SymTypeExpression", - "java.util.List", - "java.util.Optional" - }; - - - public static boolean shouldBeSupplied(String t) { - return Arrays.asList(SUPPLYLIST).contains(t); - } -} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java index 1125d19c4a..f14d4298ec 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java @@ -87,7 +87,7 @@ public String getAttributeType(ASTCDAttribute attribute) { if (getDecorationHelper().isSupplier(type)) { // a wrapped list attribute has the shape Supplier> -> unwrap to List before extracting X - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } return getTypeArgumentFromListType(type); } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java index 55378a921c..fc7f1c58ff 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java @@ -51,7 +51,7 @@ protected AbstractCreator> determineMethodDeco // If the type is wrapped (supplier), unwrap for determination ASTMCType type = ast.getMCType(); if (getDecorationHelper().isSupplier(type)) { - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } if (getMCTypeFacade().isBooleanType(type)) { diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java new file mode 100644 index 0000000000..36d5c52511 --- /dev/null +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java @@ -0,0 +1,17 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.codegen.cd2java.methods; + +import java.util.function.Supplier; + +public class __internal__Supplier implements Supplier { + Supplier supplier; + + public __internal__Supplier(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public T get() { + return supplier.get(); + } +} diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index dfb76d3da8..e38fe1e2b0 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -45,7 +45,7 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)) { // The Supplier is hidden from the user. The getter has to expose the unwrapped type (Supplier -> X) - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); templateName = "methods.SupplierGet"; } else { templateName = "methods.Get"; diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index 95ad7a9251..72d5b971b2 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -52,12 +52,12 @@ protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)){ templateName = "methods.opt.SupplierGet4Opt"; - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } else { templateName = "methods.opt.Get4Opt"; } - type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get(); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); String generatedErrorCode = service.getGeneratedErrorCode(ast.getName() + ast.printType()); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName, generatedErrorCode)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java index 75678f35d1..d790651753 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java @@ -34,7 +34,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { if (getDecorationHelper().isSupplier(ast.getMCType())) { // expose the unwrapped type (Supplier -> X) in the setter parameter; the Supplier stays hidden attribute = ast.deepClone(); - attribute.setMCType(getDecorationHelper().getReferenceTypeFromSupply(attribute.getMCType()).getMCTypeOpt().get()); + attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); templateName = "methods.SupplierSet"; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index 081fcd24b2..464011b828 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -44,12 +44,12 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)){ templateName = "methods.opt.SupplierSet4Opt"; - type = getDecorationHelper().getReferenceTypeFromSupply(type).getMCTypeOpt().get(); + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); } else { templateName = "methods.opt.Set4Opt"; } - type = getDecorationHelper().getReferenceTypeFromOptional(type).getMCTypeOpt().get().deepClone(); + type = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(type, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast, naiveAttributeName)); diff --git a/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl b/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl index 078cad0d68..a63c8fc1a4 100644 --- a/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl +++ b/monticore-generator/src/main/resources/data/DeepCloneWithParameters.ftl @@ -27,7 +27,7 @@ ${tc.signature("attributeList", "hasSuperClass")} <#elseif genHelper.isPrimitive(attrType)> result.set${methName}(${genHelper.getPlainGetter(attribute)}()); <#elseif genHelper.isOptional(attribute.getMCType())> - <#assign reference = genHelper.getReferenceTypeFromOptional(attrType)> + <#assign reference = genHelper.getReferenceTypeOfOptional(attrType)> <#assign referenceName = typeName> <#if genHelper.isString(reference) || genHelper.isAttributeOfTypeEnum(attribute)> if (isPresent${methName}()) { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java index c11850a628..92ebd72cb8 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbol.java @@ -21,11 +21,11 @@ public void setFunctionList(List methodList){ } public List getSuperClassesOnly(){ - return superTypes.get(); + return getSuperTypesList(); } public List getInterfaceList(){ - return superTypes.get(); + return getSuperTypesList(); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java index 23a30417b3..6fc1d5b0d8 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java +++ b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java @@ -9,6 +9,7 @@ import de.monticore.types.mccollectiontypes._ast.*; import de.monticore.types.mcfullgenerictypes.MCFullGenericTypesMill; import de.monticore.types.mcfullgenerictypes._ast.ASTMCWildcardTypeArgument; +import de.monticore.types.mcsimplegenerictypes.MCSimpleGenericTypesMill; import de.monticore.types.mcsimplegenerictypes._ast.ASTMCBasicGenericType; import java.util.ArrayList; @@ -248,6 +249,29 @@ public ASTMCArrayType createArrayType(final String name, int dimension) { return createArrayType(this.createQualifiedType(name), dimension); } + /** + * {@code java.util.function.Supplier} types + */ + + public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCTypeArgument inner) { + return createBasicGenericTypeOf("java.util.function.Supplier", inner); + } + + public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCType inner) { + ASTMCTypeArgument arg = MCSimpleGenericTypesMill.mCCustomTypeArgumentBuilder() + .setMCType(inner.deepClone()) + .build(); + return createSupplierTypeOf(arg); + } + + public ASTMCBasicGenericType createSupplierTypeOf(final String name) { + return createSupplierTypeOf(createBasicTypeArgumentOf(name)); + } + + public ASTMCBasicGenericType createSupplierTypeOf(final Class clazz) { + return createSupplierTypeOf(clazz.getName()); + } + /** * primitive types */ From 6aa41faff4f5f7f7e61e30b7973aa3fee45ee154 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Thu, 10 Sep 2026 10:57:16 +0200 Subject: [PATCH 09/21] use __internal__Supplier --- .../codegen/cd2java/DecorationHelper.java | 13 ++++++---- .../methods/AccessAsSupplierTypes.java | 2 +- .../cd2java/methods/__internal__Supplier.java | 17 ------------- .../main/resources/methods/SupplierSet.ftl | 2 +- .../resources/methods/opt/SupplierSet4Opt.ftl | 2 +- .../methods/opt/SupplierSetAbsent.ftl | 2 +- .../compsymbols/_symboltable/PortSymbol.java | 3 ++- .../java/de/monticore/types/MCTypeFacade.java | 4 ++-- .../symboltable/__internal__Supplier.java | 24 +++++++++++++++++++ 9 files changed, 40 insertions(+), 29 deletions(-) delete mode 100644 monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java create mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 97184a25d4..4ce187e120 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -105,12 +105,15 @@ public boolean isOptional(String type) { return "Optional".equals(Names.getSimpleName(type)); } + /** + * Checks whether the type is wrapped by the internal supplier type + */ public boolean isSupplier(String type) { int index = type.indexOf('<'); if (index != -1) { type = type.substring(0, index); } - return "Supplier".equals(Names.getSimpleName(type)); + return Names.getSimpleName(SUPPLIER_TYPE).equals(Names.getSimpleName(type)); } // The ASTMCType overloads intentionally delegate to the String checks above instead of using @@ -196,12 +199,12 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM // the initialization expression that is placed after the '=' of the field declaration String defaultValue; if (!isSupplier) { - defaultValue = inner; + defaultValue = inner; } else if (isList) { // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. - defaultValue = "com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; + defaultValue = "new " + SUPPLIER_TYPE + "<>(com.google.common.base.Suppliers.memoize(() -> " + inner + "))"; } else { - defaultValue = "() -> " + inner; + defaultValue = "new " + SUPPLIER_TYPE + "<>(() -> " + inner + ")"; } glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= " + defaultValue)); } @@ -229,7 +232,7 @@ public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { } /** - * Wraps {@code inner} into {@code Supplier} + * Wraps {@code inner} into the internal supplier type {@code __internal__Supplier} * * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... */ diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java index c991e0cf29..e8b6afaeac 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -15,7 +15,7 @@ public class AccessAsSupplierTypes { /** * Fully qualified name of the wrapper type used for lazily resolved attributes. */ - public static final String SUPPLIER_TYPE = "java.util.function.Supplier"; + public static final String SUPPLIER_TYPE = "de.monticore.symboltable.__internal__Supplier"; private static final String[] SUPPLYLIST = { "de.monticore.types.check.SymTypeExpression", diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java deleted file mode 100644 index 36d5c52511..0000000000 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/__internal__Supplier.java +++ /dev/null @@ -1,17 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.codegen.cd2java.methods; - -import java.util.function.Supplier; - -public class __internal__Supplier implements Supplier { - Supplier supplier; - - public __internal__Supplier(Supplier supplier) { - this.supplier = supplier; - } - - @Override - public T get() { - return supplier.get(); - } -} diff --git a/monticore-generator/src/main/resources/methods/SupplierSet.ftl b/monticore-generator/src/main/resources/methods/SupplierSet.ftl index 41e8259e86..32a51f6ba6 100644 --- a/monticore-generator/src/main/resources/methods/SupplierSet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierSet.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = () -> ${attribute.getName()}; +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> ${attribute.getName()}); ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl index 69d9a84eed..b0b48853bc 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute", "nativeAttributeName")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = () -> Optional.ofNullable(${attribute.getName()}); +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.ofNullable(${attribute.getName()})); ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl index 9a899540ca..8a37f755fa 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = () -> Optional.empty(); +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.empty()); ${defineHookPoint("Setter:After")} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java index 1b26b798ac..e100ed0580 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java @@ -34,7 +34,8 @@ protected PortSymbol(String name, } public boolean isTypePresent() { - return this.type != null; + // type is not an optional, so we resolve it here to check if it is null + return super.type.get() != null; } public SymTypeExpression getType() { diff --git a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java index 6fc1d5b0d8..3d3080c657 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java +++ b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java @@ -250,11 +250,11 @@ public ASTMCArrayType createArrayType(final String name, int dimension) { } /** - * {@code java.util.function.Supplier} types + * {@code de.monticore.symboltable.__internal__Supplier} types. */ public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCTypeArgument inner) { - return createBasicGenericTypeOf("java.util.function.Supplier", inner); + return createBasicGenericTypeOf("de.monticore.symboltable.__internal__Supplier", inner); } public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCType inner) { diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java new file mode 100644 index 0000000000..6d2aa5931e --- /dev/null +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java @@ -0,0 +1,24 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.symboltable; + +import java.util.function.Supplier; + +/** + * Internal marker wrapper used by generated symbol classes for symbolrule attributes whose value + * may not be resolvable yet (see {@code AccessAsSupplierTypes} in the generator). + *

+ * A dedicated type (instead of a plain {@link Supplier}) is required in case someone wants to actually return a supplier + */ +public class __internal__Supplier implements Supplier { + + protected final Supplier supplier; + + public __internal__Supplier(Supplier supplier) { + this.supplier = supplier; + } + + @Override + public T get() { + return supplier.get(); + } +} From 48fee8db94a86eeb7344c376adc36cd8bbc673a5 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Fri, 11 Sep 2026 07:51:11 +0200 Subject: [PATCH 10/21] supplierGet now warn instead if throwing --- .../src/main/resources/methods/SupplierGet.ftl | 2 +- .../src/main/resources/methods/opt/SupplierGet4Opt.ftl | 5 ++--- .../src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/monticore-generator/src/main/resources/methods/SupplierGet.ftl b/monticore-generator/src/main/resources/methods/SupplierGet.ftl index 44470de684..384679bbbe 100644 --- a/monticore-generator/src/main/resources/methods/SupplierGet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierGet.ftl @@ -2,6 +2,6 @@ ${tc.signature("attribute")} var __value = this.${attribute.getName()}.get(); if (__value == null) { - throw new IllegalStateException("Value of '${attribute.getName()}' is not available yet."); +Log.warn("Value of '${attribute.getName()}' is not available yet."); } return __value; diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl index ac245b7d34..42b9353cb4 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl @@ -3,6 +3,5 @@ ${tc.signature("attribute", "naiveAttributeName", "generatedErrorCode")} if (isPresent${naiveAttributeName}()) { return this.${attribute.getName()}.get().get(); } - Log.error("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); - // Normally this statement is not reachable - throw new IllegalStateException(); + Log.warn("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); + return null; diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl index adcb16fcd6..41286f5cf2 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl @@ -1,7 +1,8 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -var optional = this.${attribute.getName()}.get(); +var optional = this.${attribute.getName()}.get(); if (optional == null){ - throw new IllegalStateException("supplier for ${attribute.getName()} is null"); + Log.warn("supplier for ${attribute.getName()} is null"); + return false; } return optional.isPresent(); From 20bed4b9158ba9ca1b0f20ad37da8c0d5bed8d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 11 Sep 2026 11:12:03 +0200 Subject: [PATCH 11/21] rebase --- .../types/check/SymTypeExpressionFactory.java | 11 +++------- .../types/check/SymTypeOfObject.java | 17 ++++++++++----- .../types/check/SymTypeOfObjectDeSer.java | 5 +---- .../symboltable/SimpleSymbolSupplier.java | 21 +++++++++++++++++++ 4 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index b54e563478..b108f0aa4b 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -9,6 +9,8 @@ import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; +import de.monticore.symbols.basicsymbols._symboltable.*; +import de.monticore.symboltable.ISymbolSupplier; import de.se_rwth.commons.logging.Log; import java.util.ArrayList; @@ -134,15 +136,8 @@ public static SymTypeOfObject createTypeObject(TypeSymbol typeSymbol) { return new SymTypeOfObject(typeSymbol); } - /** - * @deprecated did hide the usage of surrogate, and leads to questionable code - * consider using - * {@link de.monticore.types3.util.WithinScopeBasicSymbolsResolver#resolveType(IBasicSymbolsScope, String)}, - * of creating a Surrogate explicitly (only if required) - */ - @Deprecated(forRemoval = true) public static SymTypeOfObject createTypeObject(String name, IBasicSymbolsScope enclosingScope) { - return createTypeObjectViaSurrogate(name, enclosingScope); + return new SymTypeOfObject(ISymbolSupplier.memoize(new TypeSymbolSupplier(name, enclosingScope))); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java index 23201ff391..958c359a76 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java @@ -3,6 +3,8 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symboltable.ISymbolSupplier; +import de.monticore.symboltable.SimpleSymbolSupplier; import de.monticore.types3.ISymTypeVisitor; /** @@ -12,13 +14,18 @@ */ public class SymTypeOfObject extends SymTypeExpression { - protected TypeSymbol typeSymbol; + protected ISymbolSupplier typeSymbol; /** * Constructor: with a TypeSymbolSurrogate that contains the name and enclosingScope */ public SymTypeOfObject(TypeSymbol typeSymbol) { + Preconditions.checkNotNull(typeSymbol); + this.typeSymbol = new SimpleSymbolSupplier<>(typeSymbol); + } + + public SymTypeOfObject(ISymbolSupplier typeSymbol) { Preconditions.checkNotNull(typeSymbol); this.typeSymbol = typeSymbol; } @@ -26,12 +33,12 @@ public SymTypeOfObject(TypeSymbol typeSymbol) @Override public boolean hasTypeInfo() { // should allways be true - return typeSymbol != null; + return typeSymbol.get().isPresent(); } @Override public TypeSymbol getTypeInfo() { - return typeSymbol; + return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())); } /** @@ -41,7 +48,7 @@ public TypeSymbol getTypeInfo() { */ @Deprecated(forRemoval = true) public String getObjName() { - return typeSymbol.getFullName(); + return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).getFullName(); } /** @@ -49,7 +56,7 @@ public String getObjName() { */ @Deprecated(forRemoval = true) public void setObjName(String objname) { - this.typeSymbol.setName(objname); + this.typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).setName(objname); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java index e9b1406717..6e72677c51 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java @@ -3,7 +3,6 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -43,9 +42,7 @@ public SymTypeOfObject deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - TypeSymbolSurrogate typeSym = new TypeSymbolSurrogate(objName); - typeSym.setEnclosingScope(enclosingScope); - return SymTypeExpressionFactory.createTypeObject(typeSym); + return SymTypeExpressionFactory.createTypeObject(objName, enclosingScope); } Log.error("0x823F4 Internal error: Cannot load \"" + serialized + "\" as SymTypeOfObject!"); diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java new file mode 100644 index 0000000000..4df09c6b33 --- /dev/null +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java @@ -0,0 +1,21 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.symboltable; + +import com.google.common.base.Preconditions; + +import java.util.Optional; + +public class SimpleSymbolSupplier implements ISymbolSupplier { + + private final T value; + + public SimpleSymbolSupplier(T value){ + Preconditions.checkNotNull(value); + this.value = value; + } + + @Override + public Optional get() { + return Optional.of(value); + } +} From 2e7007ef09d4f9461f93782ebe1e881c04d097ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 11 Sep 2026 11:39:47 +0200 Subject: [PATCH 12/21] Revert "spike through SymTypeOfObject now uses supplier" This reverts commit bd04066a35247a56c044fca1c2a20375a46cd682. --- .../types/check/SymTypeExpressionFactory.java | 17 ++++++++++++--- .../types/check/SymTypeOfObject.java | 18 ++++++---------- .../types/check/SymTypeOfObjectDeSer.java | 5 ++++- .../symboltable/SimpleSymbolSupplier.java | 21 ------------------- 4 files changed, 24 insertions(+), 37 deletions(-) delete mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index b108f0aa4b..ad8f2ed1a8 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -9,8 +9,12 @@ import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; -import de.monticore.symbols.basicsymbols._symboltable.*; -import de.monticore.symboltable.ISymbolSupplier; +import de.monticore.symbols.basicsymbols._symboltable.FunctionSymbol; +import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; +import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; +import de.monticore.symbols.basicsymbols._util.IBasicSymbolsTypeDispatcher; import de.se_rwth.commons.logging.Log; import java.util.ArrayList; @@ -136,8 +140,15 @@ public static SymTypeOfObject createTypeObject(TypeSymbol typeSymbol) { return new SymTypeOfObject(typeSymbol); } + /** + * @deprecated did hide the usage of surrogate, and leads to questionable code + * consider using + * {@link de.monticore.types3.util.WithinScopeBasicSymbolsResolver#resolveType(IBasicSymbolsScope, String)}, + * of creating a Surrogate explicitly (only if required) + */ + @Deprecated(forRemoval = true) public static SymTypeOfObject createTypeObject(String name, IBasicSymbolsScope enclosingScope) { - return new SymTypeOfObject(ISymbolSupplier.memoize(new TypeSymbolSupplier(name, enclosingScope))); + return createTypeObjectViaSurrogate(name, enclosingScope); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java index 958c359a76..1bd0d40b18 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java @@ -3,9 +3,8 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symboltable.ISymbolSupplier; -import de.monticore.symboltable.SimpleSymbolSupplier; import de.monticore.types3.ISymTypeVisitor; +import de.se_rwth.commons.logging.Log; /** * An objectType is a full qualified class name. @@ -14,18 +13,13 @@ */ public class SymTypeOfObject extends SymTypeExpression { - protected ISymbolSupplier typeSymbol; + protected TypeSymbol typeSymbol; /** * Constructor: with a TypeSymbolSurrogate that contains the name and enclosingScope */ public SymTypeOfObject(TypeSymbol typeSymbol) { - Preconditions.checkNotNull(typeSymbol); - this.typeSymbol = new SimpleSymbolSupplier<>(typeSymbol); - } - - public SymTypeOfObject(ISymbolSupplier typeSymbol) { Preconditions.checkNotNull(typeSymbol); this.typeSymbol = typeSymbol; } @@ -33,12 +27,12 @@ public SymTypeOfObject(ISymbolSupplier typeSymbol) { @Override public boolean hasTypeInfo() { // should allways be true - return typeSymbol.get().isPresent(); + return typeSymbol != null; } @Override public TypeSymbol getTypeInfo() { - return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())); + return typeSymbol; } /** @@ -48,7 +42,7 @@ public TypeSymbol getTypeInfo() { */ @Deprecated(forRemoval = true) public String getObjName() { - return typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).getFullName(); + return typeSymbol.getFullName(); } /** @@ -56,7 +50,7 @@ public String getObjName() { */ @Deprecated(forRemoval = true) public void setObjName(String objname) { - this.typeSymbol.get().orElseThrow(() -> new IllegalStateException("Type info is not available of" + this.getClass().getName())).setName(objname); + this.typeSymbol.setName(objname); } /** diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java index 6e72677c51..e9b1406717 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java @@ -3,6 +3,7 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -42,7 +43,9 @@ public SymTypeOfObject deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - return SymTypeExpressionFactory.createTypeObject(objName, enclosingScope); + TypeSymbolSurrogate typeSym = new TypeSymbolSurrogate(objName); + typeSym.setEnclosingScope(enclosingScope); + return SymTypeExpressionFactory.createTypeObject(typeSym); } Log.error("0x823F4 Internal error: Cannot load \"" + serialized + "\" as SymTypeOfObject!"); diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java deleted file mode 100644 index 4df09c6b33..0000000000 --- a/monticore-runtime/src/main/java/de/monticore/symboltable/SimpleSymbolSupplier.java +++ /dev/null @@ -1,21 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symboltable; - -import com.google.common.base.Preconditions; - -import java.util.Optional; - -public class SimpleSymbolSupplier implements ISymbolSupplier { - - private final T value; - - public SimpleSymbolSupplier(T value){ - Preconditions.checkNotNull(value); - this.value = value; - } - - @Override - public Optional get() { - return Optional.of(value); - } -} From 09cb3971dfd4ad751852ac04662830a226c76e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 18 Sep 2026 11:07:55 +0200 Subject: [PATCH 13/21] broken SymTypeExpressoions are wrappen in supplier for deser add getRa/ set raw removed unneccessary DeSers replaced errors with info for compatibility --- .../codegen/cd2java/DecorationHelper.java | 16 ++++----- .../SymTypeExpressionSerStrategy.java | 6 ++-- .../serialization/SymbolDeSerDecorator.java | 8 +++-- .../_symboltable/symbol/SymbolDecorator.java | 2 +- .../accessor/ListAccessorDecorator.java | 13 +++++++ .../accessor/MandatoryAccessorDecorator.java | 17 ++++++++- .../accessor/OptionalAccessorDecorator.java | 19 ++++++++-- .../methods/mutator/ListMutatorDecorator.java | 15 ++++++++ .../mutator/MandatoryMutatorDecorator.java | 20 ++++++++++- .../mutator/OptionalMutatorDecorator.java | 13 +++++++ .../symbolDeSer/Deserialize4SymbolDeSer.ftl | 25 ++++++++----- .../main/resources/methods/SupplierGet.ftl | 2 +- .../main/resources/methods/SupplierGetRaw.ftl | 3 ++ .../main/resources/methods/SupplierSetRaw.ftl | 11 ++++++ .../resources/methods/opt/SupplierGet4Opt.ftl | 2 +- .../methods/opt/SupplierIsPresent4Opt.ftl | 2 +- .../_symboltable/JavaMethodSymbolDeSer.java | 27 -------------- .../_symboltable/FunctionSymbolDeSer.java | 22 ------------ .../_symboltable/TypeSymbolDeSer.java | 24 ------------- .../_symboltable/TypeVarSymbolDeSer.java | 24 ------------- .../_symboltable/VariableSymbolDeSer.java | 22 ------------ .../java/de/monticore/types/MCTypeFacade.java | 35 +++++++++++++++---- .../_symboltable/CDClassSymbolDeSer.java | 23 ------------ .../FunctionDeclarationSymbolDeSer.java | 6 ++-- .../_symboltable/TCArtifactSymbolDeSer.java | 16 --------- .../_symboltable/TCMethodSymbolDeSer.java | 14 -------- .../_symboltable/TCVarDeclSymbolDeSer.java | 14 -------- 27 files changed, 175 insertions(+), 226 deletions(-) create mode 100644 monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl create mode 100644 monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl delete mode 100644 monticore-grammar/src/main/java/de/monticore/javalight/_symboltable/JavaMethodSymbolDeSer.java delete mode 100644 monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbolDeSer.java delete mode 100644 monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbolDeSer.java delete mode 100644 monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeVarSymbolDeSer.java delete mode 100644 monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbolDeSer.java delete mode 100644 monticore-test/02.experiments/resolving/src/main/java/de/monticore/simplecd/_symboltable/CDClassSymbolDeSer.java delete mode 100644 monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCArtifactSymbolDeSer.java delete mode 100644 monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCMethodSymbolDeSer.java delete mode 100644 monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCVarDeclSymbolDeSer.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 21e4dee425..979b05378c 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -130,6 +130,9 @@ public boolean isSupplier(ASTMCType type) { return isSupplier(type.printType()); } + public boolean shouldHaveSupplier(ASTCDAttribute attribute) { + return de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes.shouldHaveSupplier(attribute); + } public boolean isString(String type) { return "String".equals(type) || "java.lang.String".equals(type); @@ -231,31 +234,26 @@ public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); } - public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { - Preconditions.checkArgument(isSupplier(type)); - return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); - } - /** * Wraps {@code inner} into the internal supplier type {@code __internal__Supplier} * * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... */ - public ASTMCType createSupplierTypeOf(ASTMCType inner) { + public ASTMCType createInternalSupplierTypeOf(ASTMCType inner) { ASTMCTypeArgument arg = MCSimpleGenericTypesMill .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); return MCTypeFacade.getInstance().createBasicGenericTypeOf(SUPPLIER_TYPE, arg); } /** - * Wraps {@code inner} into the internal supplier type {@code __internal__Supplier} + * Wraps {@code inner} into the public {@code java.util.function.Supplier} type. * * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... */ - public ASTMCType createSupplierTypeOf(ASTMCType inner) { + public ASTMCType createStdSupplierTypeOf(ASTMCType inner) { ASTMCTypeArgument arg = MCSimpleGenericTypesMill .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); - return MCTypeFacade.getInstance().createBasicGenericTypeOf(SUPPLIER_TYPE, arg); + return MCTypeFacade.getInstance().createBasicGenericTypeOf("java.util.function.Supplier", arg); } /** diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java index 7768c76f84..2633e1850f 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java @@ -30,16 +30,16 @@ public HookPoint getListSerialHook(String 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)); + return new StringHookPoint(String.format("return () -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeMember(\"%s\", %s, %s);", attrParam, jsonParam, scopeName)); } @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)); + 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)); + return new StringHookPoint(String.format("return () -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeListMember(\"%s\", %s, %s);", attrParam, jsonParam, scopeName)); } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymbolDeSerDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymbolDeSerDecorator.java index f30037b68e..9567e6c69e 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymbolDeSerDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymbolDeSerDecorator.java @@ -211,12 +211,16 @@ protected List createDeserializeAttrMethods( List methodList = new ArrayList<>(); for (ASTCDAttribute attr : attributeList) { String methodName = DESERIALIZE + StringTransformations.capitalize(attr.getName()); + // Deserializers for supplied attributes return a supplier of that type + ASTMCType returnType = getDecorationHelper().shouldHaveSupplier(attr) + ? getDecorationHelper().createStdSupplierTypeOf(attr.getMCType()) + : attr.getMCType(); ASTCDMethod method = getCDMethodFacade() - .createMethod(PROTECTED.build(), attr.getMCType(), methodName, scopeParam, scopeJsonParam); + .createMethod(PROTECTED.build(), returnType, methodName, scopeParam, scopeJsonParam); // create wrapper function offering the deprecated interface // this one does not take the enclosing scope ASTCDMethod wrapperMethod = getCDMethodFacade() - .createMethod(PROTECTED.build(), attr.getMCType(), methodName, scopeJsonParam); + .createMethod(PROTECTED.build(), returnType, methodName, scopeJsonParam); // Check whether built-in serialization exists. If yes, use it and otherwise make method abstract Optional impl = bitser diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index 9a09e793fb..6c80bc5747 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -95,7 +95,7 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later symbolRuleAttributes.stream() .filter(a -> AccessAsSupplierTypes.shouldHaveSupplier(a.getMCType().printType())) - .forEach(a -> a.setMCType(getDecorationHelper().createSupplierTypeOf(a.getMCType()))); + .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); List symbolRuleAttributeMethods = symbolRuleAttributes diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java index 302dcb415b..f9eb92f88d 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java @@ -42,6 +42,9 @@ public ListAccessorDecorator(final GlobalExtensionManagement glex) { public List decorate(ASTCDAttribute ast) { List methods = super.decorate(ast); methods.add(createGetListMethod(ast)); + if (getDecorationHelper().isSupplier(ast.getMCType())) { + methods.add(createGetListSupplierMethod(ast)); + } return methods; } @@ -61,6 +64,16 @@ protected ASTCDMethod createGetListMethod(ASTCDAttribute ast) { return getList; } + protected ASTCDMethod createGetListSupplierMethod(ASTCDAttribute ast) { + String name = "get" + capitalizedAttributeNameWithOutS + "ListSupplier"; + de.monticore.types.mcbasictypes._ast.ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDMethod method = this.getCDMethodFacade().createMethod( + de.monticore.cd.facade.CDModifier.PUBLIC.build(), supplierType, name); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierGetRaw", ast)); + return method; + } + @Override protected List getMethodSignatures() { return Arrays.asList( diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index e38fe1e2b0..51a536c68a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -29,7 +29,12 @@ public MandatoryAccessorDecorator(final GlobalExtensionManagement glex) { @Override public List decorate(final ASTCDAttribute ast) { - return new ArrayList<>(Collections.singletonList(createGetter(ast))); + List methods = new ArrayList<>(); + methods.add(createGetter(ast)); + if (getDecorationHelper().isSupplier(ast.getMCType())) { + methods.add(createSupplierGetter(ast)); + } + return methods; } protected ASTCDMethod createGetter(final ASTCDAttribute ast) { @@ -55,4 +60,14 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } + + protected ASTCDMethod createSupplierGetter(final ASTCDAttribute ast) { + String name = String.format(GET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))) + "Supplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), supplierType, name); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierGetRaw", ast)); + return method; + } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index 72d5b971b2..1fa6baa189 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -36,9 +36,13 @@ public OptionalAccessorDecorator(final GlobalExtensionManagement glex, @Override public List decorate(final ASTCDAttribute ast) { naiveAttributeName = getNaiveAttributeName(ast); - ASTCDMethod get = createGetMethod(ast); - ASTCDMethod isPresent = createIsPresentMethod(ast); - return new ArrayList<>(Arrays.asList(get, isPresent)); + List methods = new ArrayList<>(); + methods.add(createGetMethod(ast)); + methods.add(createIsPresentMethod(ast)); + if (getDecorationHelper().isSupplier(ast.getMCType())) { + methods.add(createSupplierGetMethod(ast)); + } + return methods; } protected String getNaiveAttributeName(ASTCDAttribute astcdAttribute) { @@ -64,6 +68,15 @@ protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { return method; } + protected ASTCDMethod createSupplierGetMethod(final ASTCDAttribute ast) { + String name = String.format(GET, naiveAttributeName) + "Supplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), supplierType, name); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierGetRaw", ast)); + return method; + } + protected ASTCDMethod createIsPresentMethod(final ASTCDAttribute ast) { String name = String.format(IS_PRESENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), getMCTypeFacade().createBooleanType(), name); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java index ac932899ff..e376244771 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java @@ -38,6 +38,9 @@ public ListMutatorDecorator(final GlobalExtensionManagement glex) { public List decorate(ASTCDAttribute ast) { List methods = createSetter(ast); methods.add(createSetListMethod(ast)); + if (getDecorationHelper().isSupplier(ast.getMCType())) { + methods.add(createSetListSupplierMethod(ast)); + } return methods; } @@ -56,6 +59,18 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { return getList; } + protected ASTCDMethod createSetListSupplierMethod(ASTCDAttribute ast) { + String name = "set" + capitalizedAttributeNameWithOutS + "ListSupplier"; + de.monticore.types.mcbasictypes._ast.ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + de.monticore.cd4codebasis._ast.ASTCDParameter parameter = + this.getCDParameterFacade().createParameter(supplierType, ast.getName()); + ASTCDMethod method = this.getCDMethodFacade().createMethod( + de.monticore.cd.facade.CDModifier.PUBLIC.build(), name, parameter); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierSetRaw", ast)); + return method; + } + protected List createSetter(ASTCDAttribute ast){ return super.decorate(ast); } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java index d790651753..d155ede680 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java @@ -6,6 +6,7 @@ import de.monticore.codegen.cd2java.AbstractCreator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -25,7 +26,11 @@ public MandatoryMutatorDecorator(final GlobalExtensionManagement glex) { @Override public List decorate(final ASTCDAttribute ast) { - return new ArrayList<>(Collections.singletonList(createSetter(ast))); + List methods = new ArrayList<>(Collections.singletonList(createSetter(ast))); + if (getDecorationHelper().isSupplier(ast.getMCType())) { + methods.add(createSupplierSetter(ast)); + } + return methods; } protected ASTCDMethod createSetter(final ASTCDAttribute ast) { @@ -43,4 +48,17 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } + + + protected ASTCDMethod createSupplierSetter(final ASTCDAttribute ast) { + ASTCDAttribute attribute = ast.deepClone(); + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + attribute.setMCType(supplierType); + + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))) + "Supplier"; + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierSetRaw", ast)); + return method; + } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index 464011b828..f9b8c77f59 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -34,6 +34,9 @@ public List decorate(final ASTCDAttribute ast) { naiveAttributeName = StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName())); methodList.add(createSetMethod(ast)); methodList.add(createSetAbsentMethod(ast)); + if (getDecorationHelper().isSupplier(ast.getMCType())) { + methodList.add(createSupplierSetMethod(ast)); + } return methodList; } @@ -56,6 +59,16 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { return method; } + protected ASTCDMethod createSupplierSetMethod(final ASTCDAttribute ast) { + String name = String.format(SET, naiveAttributeName) + "Supplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierSetRaw", ast)); + return method; + } + protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute ast) { String name = String.format(SET_ABSENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name); diff --git a/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl b/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl index dd739b6960..4ddef86ab3 100644 --- a/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl +++ b/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl @@ -21,14 +21,16 @@ ${tc.signature("symTabMill", "symbolFullName", "symbolSimpleName","symbolRuleAtt } <#list symbolRuleAttribute as attr> - <#if genHelper.isOptional(attr.getMCType())> - if (deserialize${attr.getName()?cap_first}(symbolJson).isPresent()) { - builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson).get()); - } else { - builder.${genHelper.getPlainSetter(attr)}Absent(); - } - <#else> - builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson)); + <#if !genHelper.shouldHaveSupplier(attr)> + <#if genHelper.isOptional(attr.getMCType())> + if (deserialize${attr.getName()?cap_first}(symbolJson).isPresent()) { + builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson).get()); + } else { + builder.${genHelper.getPlainSetter(attr)}Absent(); + } + <#else> + builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson)); + @@ -48,5 +50,12 @@ ${tc.signature("symTabMill", "symbolFullName", "symbolSimpleName","symbolRuleAtt ${symbolFullName} symbol = builder.build(); + <#list symbolRuleAttribute as attr> + <#if genHelper.shouldHaveSupplier(attr)> + <#-- supplied attributes are not resolved immediately, so we store the supplied --> + symbol.${genHelper.getPlainSetter(attr)}Supplier(deserialize${attr.getName()?cap_first}(scope, symbolJson)); + + + deserializeAddons(symbol, symbolJson); return symbol; \ No newline at end of file diff --git a/monticore-generator/src/main/resources/methods/SupplierGet.ftl b/monticore-generator/src/main/resources/methods/SupplierGet.ftl index 384679bbbe..0e92487df9 100644 --- a/monticore-generator/src/main/resources/methods/SupplierGet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierGet.ftl @@ -2,6 +2,6 @@ ${tc.signature("attribute")} var __value = this.${attribute.getName()}.get(); if (__value == null) { -Log.warn("Value of '${attribute.getName()}' is not available yet."); +Log.info("Value of '${attribute.getName()}' is not available yet.", "get${attribute.getName()}"); } return __value; diff --git a/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl new file mode 100644 index 0000000000..1f1de2a52a --- /dev/null +++ b/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl @@ -0,0 +1,3 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +return this.${attribute.getName()}; diff --git a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl new file mode 100644 index 0000000000..a5b930ce41 --- /dev/null +++ b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl @@ -0,0 +1,11 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +<#assign genHelper = glex.getGlobalVar("astHelper")> +${defineHookPoint("Setter:Before")} +<#-- avoid double-wrapping when the caller passes back an already-wrapped supplier --> +if (${attribute.getName()} instanceof de.monticore.symboltable.__internal__Supplier) { + this.${attribute.getName()} = (${genHelper.printType(attribute.getMCType())}) ${attribute.getName()}; +} else { + this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); +} +${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl index 42b9353cb4..5c78414743 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierGet4Opt.ftl @@ -3,5 +3,5 @@ ${tc.signature("attribute", "naiveAttributeName", "generatedErrorCode")} if (isPresent${naiveAttributeName}()) { return this.${attribute.getName()}.get().get(); } - Log.warn("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty."); + Log.info("0xA7003${generatedErrorCode} get for ${naiveAttributeName} can't return a value. Attribute is empty.", "get${attribute.getName()}"); return null; diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl index 41286f5cf2..2167c5d80d 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierIsPresent4Opt.ftl @@ -2,7 +2,7 @@ ${tc.signature("attribute")} var optional = this.${attribute.getName()}.get(); if (optional == null){ - Log.warn("supplier for ${attribute.getName()} is null"); + Log.info("supplier for ${attribute.getName()} is null", "isPresent${attribute.getName()}"); return false; } return optional.isPresent(); diff --git a/monticore-grammar/src/main/java/de/monticore/javalight/_symboltable/JavaMethodSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/javalight/_symboltable/JavaMethodSymbolDeSer.java deleted file mode 100644 index 37d97b76c2..0000000000 --- a/monticore-grammar/src/main/java/de/monticore/javalight/_symboltable/JavaMethodSymbolDeSer.java +++ /dev/null @@ -1,27 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.javalight._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -import java.util.List; - -public class JavaMethodSymbolDeSer extends JavaMethodSymbolDeSerTOP { - - @Override - protected List deserializeExceptions(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("exceptions", symbolJson); - } - - @Override - protected List deserializeAnnotations(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("annotations", symbolJson); - } - - @Override - protected SymTypeExpression deserializeType(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeMember("type", symbolJson); - } - -} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbolDeSer.java deleted file mode 100644 index a03bd9ed91..0000000000 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbolDeSer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symbols.basicsymbols._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -public class FunctionSymbolDeSer extends FunctionSymbolDeSerTOP { - - @Override - public SymTypeExpression deserializeType(JsonObject symbolJson) { - // support deprecated behavior - return deserializeType(null, symbolJson); - } - - @Override - public SymTypeExpression deserializeType( - IBasicSymbolsScope scope, JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeMember("type", symbolJson, scope); - } - -} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbolDeSer.java deleted file mode 100644 index e8f468780a..0000000000 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeSymbolDeSer.java +++ /dev/null @@ -1,24 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symbols.basicsymbols._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -import java.util.List; - -public class TypeSymbolDeSer extends TypeSymbolDeSerTOP { - - @Override - public List deserializeSuperTypes(JsonObject symbolJson) { - // support deprecated behavior - return deserializeSuperTypes(null, symbolJson); - } - - @Override - public List deserializeSuperTypes( - IBasicSymbolsScope scope, JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson, scope); - } - -} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeVarSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeVarSymbolDeSer.java deleted file mode 100644 index 2c34a141ae..0000000000 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/TypeVarSymbolDeSer.java +++ /dev/null @@ -1,24 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symbols.basicsymbols._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -import java.util.List; - -public class TypeVarSymbolDeSer extends TypeVarSymbolDeSerTOP { - - @Override - public List deserializeSuperTypes(JsonObject symbolJson) { - // support deprecated behavior - return deserializeSuperTypes(null, symbolJson); - } - - @Override - public List deserializeSuperTypes( - IBasicSymbolsScope scope, JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson, scope); - } - -} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbolDeSer.java deleted file mode 100644 index a2069ffc57..0000000000 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbolDeSer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symbols.basicsymbols._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -public class VariableSymbolDeSer extends VariableSymbolDeSerTOP { - - @Override - public SymTypeExpression deserializeType(JsonObject symbolJson) { - // support deprecated behavior - return deserializeType(null, symbolJson); - } - - @Override - public SymTypeExpression deserializeType( - IBasicSymbolsScope scope, JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeMember("type", symbolJson, scope); - } - -} diff --git a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java index 3d3080c657..24cf2a618f 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java +++ b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java @@ -253,23 +253,44 @@ public ASTMCArrayType createArrayType(final String name, int dimension) { * {@code de.monticore.symboltable.__internal__Supplier} types. */ - public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCTypeArgument inner) { + public ASTMCBasicGenericType createInternalSupplierTypeOf(final ASTMCTypeArgument inner) { return createBasicGenericTypeOf("de.monticore.symboltable.__internal__Supplier", inner); } - public ASTMCBasicGenericType createSupplierTypeOf(final ASTMCType inner) { + public ASTMCBasicGenericType createInternalSupplierTypeOf(final ASTMCType inner) { ASTMCTypeArgument arg = MCSimpleGenericTypesMill.mCCustomTypeArgumentBuilder() .setMCType(inner.deepClone()) .build(); - return createSupplierTypeOf(arg); + return createInternalSupplierTypeOf(arg); } - public ASTMCBasicGenericType createSupplierTypeOf(final String name) { - return createSupplierTypeOf(createBasicTypeArgumentOf(name)); + public ASTMCBasicGenericType createInternalSupplierTypeOf(final String name) { + return createInternalSupplierTypeOf(createBasicTypeArgumentOf(name)); } - public ASTMCBasicGenericType createSupplierTypeOf(final Class clazz) { - return createSupplierTypeOf(clazz.getName()); + public ASTMCBasicGenericType createInternalSupplierTypeOf(final Class clazz) { + return createInternalSupplierTypeOf(clazz.getName()); + } + + /** + * {@code java.util.function.Supplier } types. + */ + + public ASTMCBasicGenericType createStdSupplierTypeOf(final ASTMCTypeArgument inner) { + return createBasicGenericTypeOf("java.util.function.Supplier", inner); + } + + public ASTMCBasicGenericType createStdSupplierTypeOf(ASTMCType inner) { + ASTMCTypeArgument arg = MCSimpleGenericTypesMill.mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); + return createStdSupplierTypeOf(arg); + } + + public ASTMCBasicGenericType createStdSupplierTypeOf(final String name) { + return createStdSupplierTypeOf(createBasicTypeArgumentOf(name)); + } + + public ASTMCBasicGenericType createStdSupplierTypeOf(final Class clazz) { + return createStdSupplierTypeOf(clazz.getName()); } /** diff --git a/monticore-test/02.experiments/resolving/src/main/java/de/monticore/simplecd/_symboltable/CDClassSymbolDeSer.java b/monticore-test/02.experiments/resolving/src/main/java/de/monticore/simplecd/_symboltable/CDClassSymbolDeSer.java deleted file mode 100644 index 9bb113dc7a..0000000000 --- a/monticore-test/02.experiments/resolving/src/main/java/de/monticore/simplecd/_symboltable/CDClassSymbolDeSer.java +++ /dev/null @@ -1,23 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.simplecd._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -import java.util.List; - -public class CDClassSymbolDeSer extends CDClassSymbolDeSerTOP{ - - @Override - protected void serializeSuperTypes(List superTypes, SimpleCDSymbols2Json s2j) { - SymTypeExpressionDeSer.serializeMember(s2j.printer, "superTypes", superTypes); - } - - @Override - protected List deserializeSuperTypes(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); - } - - -} diff --git a/monticore-test/02.experiments/unknownScopes/src/main/java/foo/_symboltable/FunctionDeclarationSymbolDeSer.java b/monticore-test/02.experiments/unknownScopes/src/main/java/foo/_symboltable/FunctionDeclarationSymbolDeSer.java index 675837fb5d..7fffc96dc6 100644 --- a/monticore-test/02.experiments/unknownScopes/src/main/java/foo/_symboltable/FunctionDeclarationSymbolDeSer.java +++ b/monticore-test/02.experiments/unknownScopes/src/main/java/foo/_symboltable/FunctionDeclarationSymbolDeSer.java @@ -4,14 +4,16 @@ import de.monticore.symboltable.serialization.json.JsonObject; import de.monticore.types.check.SymTypeExpression; +import java.util.function.Supplier; + public class FunctionDeclarationSymbolDeSer extends FunctionDeclarationSymbolDeSerTOP { @Override protected void serializeType(SymTypeExpression type, FooSymbols2Json s2j) {} @Override - protected SymTypeExpression deserializeType(JsonObject symbolJson) { - return null; + protected Supplier deserializeType(JsonObject symbolJson) { + return () -> null; } } diff --git a/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCArtifactSymbolDeSer.java b/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCArtifactSymbolDeSer.java deleted file mode 100644 index 72a8ed7537..0000000000 --- a/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCArtifactSymbolDeSer.java +++ /dev/null @@ -1,16 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package mc.typechecktest._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -import java.util.List; - -public class TCArtifactSymbolDeSer extends TCArtifactSymbolDeSerTOP { - - @Override - protected List deserializeSuperTypes(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); - } -} diff --git a/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCMethodSymbolDeSer.java b/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCMethodSymbolDeSer.java deleted file mode 100644 index 13b29e8223..0000000000 --- a/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCMethodSymbolDeSer.java +++ /dev/null @@ -1,14 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package mc.typechecktest._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -public class TCMethodSymbolDeSer extends TCMethodSymbolDeSerTOP { - - @Override - protected SymTypeExpression deserializeType(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeMember("type", symbolJson); - } -} diff --git a/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCVarDeclSymbolDeSer.java b/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCVarDeclSymbolDeSer.java deleted file mode 100644 index 6b1df014b1..0000000000 --- a/monticore-test/monticore-grammar-it/src/main/java/mc/typechecktest/_symboltable/TCVarDeclSymbolDeSer.java +++ /dev/null @@ -1,14 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package mc.typechecktest._symboltable; - -import de.monticore.symboltable.serialization.json.JsonObject; -import de.monticore.types.check.SymTypeExpression; -import de.monticore.types.check.SymTypeExpressionDeSer; - -public class TCVarDeclSymbolDeSer extends TCVarDeclSymbolDeSerTOP { - - @Override - protected SymTypeExpression deserializeType(JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeMember("type", symbolJson); - } -} From 58c28a69ca0875b1d0afab057a3eef1b49915f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Fri, 18 Sep 2026 15:39:03 +0200 Subject: [PATCH 14/21] Builder can use supplier scopes can use supplier removed wrong desers --- .../codegen/cd2java/DecorationHelper.java | 14 ++++++-- .../_ast/builder/BuilderDecorator.java | 6 +++- .../BuilderListMutatorDecorator.java | 20 ++++++++++- .../BuilderMandatoryMutatorDecorator.java | 27 +++++++++++++-- .../BuilderOptionalMutatorDecorator.java | 34 +++++++++++++++++-- .../InheritedBuilderListMutatorDecorator.java | 15 ++++++++ ...ritedBuilderMandatoryMutatorDecorator.java | 24 +++++++++++-- ...eritedBuilderOptionalMutatorDecorator.java | 16 ++++++++- .../scope/ScopeClassDecorator.java | 4 +++ .../scope/ScopeInterfaceDecorator.java | 6 +++- .../serialization/ScopeDeSerDecorator.java | 11 ++++-- .../symbol/SymbolBuilderDecorator.java | 5 +++ .../_symboltable/symbol/SymbolDecorator.java | 2 +- .../methods/AccessAsSupplierTypes.java | 13 +++++-- .../_ast/builder/SupplierSet4ASTBuilder.ftl | 6 ++++ .../builder/SupplierSetRaw4ASTBuilder.ftl | 12 +++++++ .../builder/opt/SupplierSet4ASTBuilderOpt.ftl | 4 +++ .../opt/SupplierSetAbsent4ASTBuilderOpt.ftl | 4 +++ .../scopeDeSer/DeserializeArtifactScope.ftl | 11 +++--- .../scopeDeSer/DeserializeScope.ftl | 11 +++--- .../symbolDeSer/Deserialize4SymbolDeSer.ftl | 27 ++++++--------- .../_symboltable/symbol/BuildSymbol.ftl | 22 ++++++------ .../mc/feature/scoperules/ScoperuleTest.mc4 | 4 +-- .../mc/feature/symbolrules/SymbolruleTest.mc4 | 4 +-- .../_symboltable/ScoperuleTestDeSer.java | 6 ++-- .../_symboltable/SymbolruleListTestDeSer.java | 9 +++-- .../_symboltable/ITestSymbolDeSer.java | 9 +++-- .../_symboltable/SymbolruleTestDeSer.java | 6 ++-- .../_symboltable/Test1SymbolDeSer.java | 11 ++++-- .../_symboltable/Test2SymbolDeSer.java | 9 +++-- 30 files changed, 278 insertions(+), 74 deletions(-) create mode 100644 monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl create mode 100644 monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl create mode 100644 monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl create mode 100644 monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 979b05378c..a2730be8e0 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -291,12 +291,22 @@ public boolean isAttributeOfTypeEnum(ASTCDAttribute attr) { return ((CDTypeSymbol) type.get()).isIsEnum(); } + /** + * unwraps the internal supplier type (Supplier<X> -> X); returns the type unchanged if it is not wrapped + */ + public ASTMCType unwrapSupplier(ASTMCType type) { + if (isSupplier(type)) { + return getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + } + return type; + } + /** * methods return correct getters or setters for a special attribut * needed in templates */ public String getPlainGetter(ASTCDAttribute ast) { - String astType = CD4CodeMill.prettyPrint(ast.getMCType(), false); + String astType = CD4CodeMill.prettyPrint(unwrapSupplier(ast.getMCType()), false); StringBuilder sb = new StringBuilder(); // Do not use CDTypes.isBoolean() because only primitive boolean uses GET_PREFIX_BOOLEAN if (astType.equals("boolean")) { @@ -319,7 +329,7 @@ public String getPlainGetter(ASTCDAttribute ast) { public String getPlainSetter(ASTCDAttribute ast) { StringBuilder sb = new StringBuilder(SET_PREFIX).append( StringTransformations.capitalize(getNativeAttributeName(ast.getName()))); - String astType = CD4CodeMill.prettyPrint(ast.getMCType(), false); + String astType = CD4CodeMill.prettyPrint(unwrapSupplier(ast.getMCType()), false); if (isListType(astType)) { if (hasDerivedAttributeName(ast) && ast.getName().endsWith(TransformationHelper.LIST_SUFFIX)) { sb.replace(sb.length() - TransformationHelper.LIST_SUFFIX.length(), diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java index b205ab7499..1587bd235a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java @@ -133,7 +133,11 @@ public ASTCDClass decorate(final ASTCDClass domainClass) throws DecorateExceptio } protected void addAttributeDefaultValues(ASTCDAttribute attribute) { - if (getDecorationHelper().isListType(CD4CodeMill.prettyPrint(attribute.getMCType(), false))) { + if (getDecorationHelper().isSupplier(attribute.getMCType())) { + // a supplier-wrapped attribute must have a non-null default supplier, otherwise build() would + // hand the symbol a null field where a Supplier is expected + getDecorationHelper().addAttributeDefaultValues(attribute, glex); + } else if (getDecorationHelper().isListType(CD4CodeMill.prettyPrint(attribute.getMCType(), false))) { this.replaceTemplate(VALUE, attribute, new StringHookPoint("= new java.util.ArrayList<>()")); } else if (getDecorationHelper().isOptional(CD4CodeMill.prettyPrint(attribute.getMCType(), false))) { diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java index d8098c2f06..a037349824 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java @@ -15,6 +15,7 @@ import java.util.stream.Collectors; import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY; +import static de.monticore.cd.facade.CDModifier.PUBLIC; /** * changes return type of builder setters for list attributes @@ -58,7 +59,24 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { ASTCDMethod method = this.getCDMethodFacade().createMethodByDefinition(signature); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); method.setMCReturnType(returnType); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.Set4ASTBuilder", ast)); + + String templateName = getDecorationHelper().isSupplier(ast.getMCType()) + ? "_ast.builder.SupplierSet4ASTBuilder" + : "_ast.builder.Set4ASTBuilder"; + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); + return method; + } + + @Override + protected ASTCDMethod createSetListSupplierMethod(ASTCDAttribute ast) { + String name = "set" + capitalizedAttributeNameWithOutS + "ListSupplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); + ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); + method.setMCReturnType(returnType); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SupplierSetRaw4ASTBuilder", ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java index 21bd56009e..192e67a523 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java @@ -26,9 +26,30 @@ public BuilderMandatoryMutatorDecorator(final GlobalExtensionManagement glex, @Override protected ASTCDMethod createSetter(final ASTCDAttribute ast) { - String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); - ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(ast)); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.Set4ASTBuilder", ast)); + ASTCDAttribute attribute = ast; + String templateName = "_ast.builder.Set4ASTBuilder"; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + attribute = ast.deepClone(); + attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); + templateName = "_ast.builder.SupplierSet4ASTBuilder"; + } + + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); + return method; + } + + @Override + protected ASTCDMethod createSupplierSetter(final ASTCDAttribute ast) { + ASTCDAttribute attribute = ast.deepClone(); + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + attribute.setMCType(supplierType); + + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))) + "Supplier"; + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SupplierSetRaw4ASTBuilder", ast)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java index 147a826c44..d52ae1fad1 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java @@ -30,12 +30,35 @@ public BuilderOptionalMutatorDecorator(final GlobalExtensionManagement glex, @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); + + ASTMCType type = attribute.getMCType().deepClone(); + String templateName; + if (getDecorationHelper().isSupplier(type)) { + templateName = "_ast.builder.opt.SupplierSet4ASTBuilderOpt"; + type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + } else { + templateName = "_ast.builder.opt.Set4ASTBuilderOpt"; + } + + ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); method.setMCReturnType(returnType); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.opt.Set4ASTBuilderOpt", attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, attribute)); + return method; + } + + @Override + protected ASTCDMethod createSupplierSetMethod(final ASTCDAttribute ast) { + String name = String.format(SET, naiveAttributeName) + "Supplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); + ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); + method.setMCReturnType(returnType); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SupplierSetRaw4ASTBuilder", ast)); return method; } @@ -45,7 +68,12 @@ protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute attribute) { ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); method.setMCReturnType(returnType); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.opt.SetAbsent4ASTBuilderOpt", attribute)); + + String templateName = getDecorationHelper().isSupplier(attribute.getMCType()) + ? "_ast.builder.opt.SupplierSetAbsent4ASTBuilderOpt" + : "_ast.builder.opt.SetAbsent4ASTBuilderOpt"; + + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, attribute)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java index fa591abae8..ee706692b7 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java @@ -3,6 +3,7 @@ import de.monticore.cdbasis._ast.ASTCDAttribute; import de.monticore.cd4codebasis._ast.ASTCDMethod; +import de.monticore.cd4codebasis._ast.ASTCDParameter; import de.monticore.codegen.cd2java._ast.builder.buildermethods.BuilderListMutatorDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; @@ -11,6 +12,7 @@ import de.monticore.types.mcbasictypes.MCBasicTypesMill; import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY; +import static de.monticore.cd.facade.CDModifier.PUBLIC; /** * changes return type of builder setters for list attributes @@ -30,4 +32,17 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SetInherited", ast, "set" + capitalizedAttributeNameWithS + "List")); return method; } + + @Override + protected ASTCDMethod createSetListSupplierMethod(ASTCDAttribute ast) { + String name = "set" + capitalizedAttributeNameWithOutS + "ListSupplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); + ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); + method.setMCReturnType(returnType); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SetInherited", ast, name)); + return method; + } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java index 90aca96882..ea9f565c67 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java @@ -24,9 +24,27 @@ public InheritedBuilderMandatoryMutatorDecorator(final GlobalExtensionManagement @Override protected ASTCDMethod createSetter(final ASTCDAttribute ast) { - String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); - ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(ast)); - this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SetInherited", ast, name)); + ASTCDAttribute attribute = ast; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + attribute = ast.deepClone(); + attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); + } + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SetInherited", attribute, name)); + return method; + } + + @Override + protected ASTCDMethod createSupplierSetter(final ASTCDAttribute ast) { + ASTCDAttribute attribute = ast.deepClone(); + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + attribute.setMCType(supplierType); + + String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))) + "Supplier"; + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SetInherited", attribute, name)); return method; } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java index b6df5bc534..09079228c6 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java @@ -28,7 +28,8 @@ public InheritedBuilderOptionalMutatorDecorator(final GlobalExtensionManagement @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(attribute.getMCType()).getMCTypeOpt().get().deepClone(); + ASTMCType type = getDecorationHelper().unwrapSupplier(attribute.getMCType()); + ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); @@ -37,6 +38,19 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { return method; } + @Override + protected ASTCDMethod createSupplierSetMethod(final ASTCDAttribute ast) { + String name = String.format(SET, naiveAttributeName) + "Supplier"; + ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( + "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); + ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); + method.setMCReturnType(returnType); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("_ast.builder.SetInherited", ast, name)); + return method; + } + @Override protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute attribute) { String name = String.format(SET_ABSENT, naiveAttributeName); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java index 08aed607c6..c783c1c31d 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java @@ -17,6 +17,7 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -95,6 +96,9 @@ public ASTCDClass decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilationUnit .flatMap(List::stream) .map(ASTCDAttribute::deepClone) .collect(Collectors.toList()); + scopeRuleAttributeList.stream() + .filter(AccessAsSupplierTypes::shouldHaveSupplier) + .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); scopeRuleAttributeList .forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java index 8de398a602..abf9a25095 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java @@ -15,6 +15,7 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -93,7 +94,10 @@ public ASTCDInterface decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilation .map(ASTCDClass::getCDAttributeList) .flatMap(List::stream) .map(ASTCDAttribute::deepClone) - .toList(); + .collect(Collectors.toList()); + scopeRuleAttributes.stream() + .filter(AccessAsSupplierTypes::shouldHaveSupplier) + .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); List scopeRuleMethodList = scopeInput.deepClone().getCDDefinition().getCDClassesList() .stream() diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/ScopeDeSerDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/ScopeDeSerDecorator.java index 9d2ea934d1..0afe4714ce 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/ScopeDeSerDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/ScopeDeSerDecorator.java @@ -22,6 +22,7 @@ import de.monticore.symbols.basicsymbols._symboltable.DiagramSymbol; import de.monticore.symboltable.serialization.ISymbolDeSer; import de.monticore.types.mcbasictypes._ast.ASTMCQualifiedType; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.se_rwth.commons.StringTransformations; import java.util.*; @@ -264,12 +265,16 @@ protected List createDeserializeAttrMethods( List methodList = new ArrayList<>(); for (ASTCDAttribute attr : attributeList) { String methodName = DESERIALIZE + StringTransformations.capitalize(attr.getName()); + // Deserializers for supplied attributes return a supplier of that type + ASTMCType returnType = getDecorationHelper().shouldHaveSupplier(attr) + ? getDecorationHelper().createStdSupplierTypeOf(attr.getMCType()) + : attr.getMCType(); ASTCDMethod method = getCDMethodFacade() - .createMethod(PROTECTED.build(), attr.getMCType(), methodName, scopeParam, scopeJsonParam); + .createMethod(PROTECTED.build(), returnType, methodName, scopeParam, scopeJsonParam); // create wrapper functions offering the deprecated interface // this one does not take the enclosing scope ASTCDMethod wrapperMethod = getCDMethodFacade() - .createMethod(PROTECTED.build(), attr.getMCType(), methodName, scopeJsonParam); + .createMethod(PROTECTED.build(), returnType, methodName, scopeJsonParam); // Check whether built-in serialization exists. If yes, use it and otherwise make method abstract Optional impl = bitser @@ -295,7 +300,7 @@ protected List createDeserializeAttrMethods( ASTCDParameter iScopeParam = getCDParameterFacade().createParameter(getMCTypeFacade() .createQualifiedType(I_SCOPE), scopeParam.getName()); ASTCDMethod wrapperMethod2 = getCDMethodFacade() - .createMethod(PROTECTED.build(), attr.getMCType(), methodName, iScopeParam, scopeJsonParam); + .createMethod(PROTECTED.build(), returnType, methodName, iScopeParam, scopeJsonParam); String errorCode = symbolTableService.getGeneratedErrorCode(methodName); this.replaceTemplate(EMPTY_BODY, wrapperMethod2, new TemplateHookPoint( DESERIALIZE_IS_TEMPL, methodName, scopeParam.getMCType().printType(), errorCode)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java index 564d447524..f36c504b83 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java @@ -12,6 +12,7 @@ import de.monticore.codegen.cd2java._ast.builder.BuilderDecorator; import de.monticore.codegen.cd2java._ast.builder.buildermethods.BuilderMutatorMethodDecorator; import de.monticore.codegen.cd2java._symboltable.SymbolTableService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.HookPoint; import de.monticore.generating.templateengine.StringHookPoint; @@ -75,6 +76,10 @@ public ASTCDClass decorate(final ASTCDClass symbolClass) { } } + decoratedSymbolClass.getCDAttributeList().stream() + .filter(AccessAsSupplierTypes::shouldHaveSupplier) + .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); + builderDecorator.setPrintBuildMethodTemplate(false); ASTCDClass symbolBuilder = builderDecorator.decorate(decoratedSymbolClass); builderDecorator.setPrintBuildMethodTemplate(true); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index 6c80bc5747..466a175994 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -94,7 +94,7 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later symbolRuleAttributes.stream() - .filter(a -> AccessAsSupplierTypes.shouldHaveSupplier(a.getMCType().printType())) + .filter(AccessAsSupplierTypes::shouldHaveSupplier) .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java index e8b6afaeac..89fe31bc47 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -20,11 +20,18 @@ public class AccessAsSupplierTypes { private static final String[] SUPPLYLIST = { "de.monticore.types.check.SymTypeExpression", "java.util.List", - "java.util.Optional" + "java.util.Optional", + "List", + "Optional", + "SymTypeExpression", + "java.util.List", + "java.util.Optional", + "List", + "Optional" }; /** - * @param type the fully qualified, printed attribute type + * @param type the printed attribute type * @return whether an attribute of this type should be wrapped in / accessed via a {@code Supplier} */ public static boolean shouldHaveSupplier(String type) { @@ -32,7 +39,7 @@ public static boolean shouldHaveSupplier(String type) { } public static boolean shouldHaveSupplier(ASTCDAttribute attribute) { - return shouldHaveSupplier(attribute.getMCType().printType()); + return shouldHaveSupplier(attribute.printType()); } } diff --git a/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl b/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl new file mode 100644 index 0000000000..7e8de17b47 --- /dev/null +++ b/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl @@ -0,0 +1,6 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +${defineHookPoint("Setter:Before")} +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> ${attribute.getName()}); +${defineHookPoint("Setter:After")} +return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl new file mode 100644 index 0000000000..4370f452a1 --- /dev/null +++ b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl @@ -0,0 +1,12 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +<#assign genHelper = glex.getGlobalVar("astHelper")> +${defineHookPoint("Setter:Before")} +<#-- avoid double-wrapping when the caller passes back an already-wrapped supplier --> +if (${attribute.getName()} instanceof de.monticore.symboltable.__internal__Supplier) { + this.${attribute.getName()} = (${genHelper.printType(attribute.getMCType())}) ${attribute.getName()}; +} else { + this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); +} +${defineHookPoint("Setter:After")} +return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl new file mode 100644 index 0000000000..e56916e5d2 --- /dev/null +++ b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl @@ -0,0 +1,4 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.ofNullable(${attribute.getName()})); +return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl new file mode 100644 index 0000000000..e08c2025cd --- /dev/null +++ b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl @@ -0,0 +1,4 @@ +<#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("attribute")} +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.empty()); +return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeArtifactScope.ftl b/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeArtifactScope.ftl index 07ef78215f..70790c07b4 100644 --- a/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeArtifactScope.ftl +++ b/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeArtifactScope.ftl @@ -9,15 +9,18 @@ ${tc.signature("symTabMill", "artifactScope", "scopeRuleAttrList")} scope.setExportingSymbols(true); <#list scopeRuleAttrList as attr> - <#if genHelper.isOptional(attr.getMCType())> + <#assign setter = genHelper.getPlainSetter(attr)> + <#if genHelper.shouldHaveSupplier(attr)> + scope.${setter}Supplier(deserialize${attr.getName()?cap_first}(scope, scopeJson)); + <#elseif genHelper.isOptional(attr.getMCType())> ${attr.printType()} _${attr.getName()} = deserialize${attr.getName()?cap_first}(scope, scopeJson); if (_${attr.getName()}.isPresent()) { - scope.${genHelper.getPlainSetter(attr)}(_${attr.getName()}.get()); + scope.${setter}(_${attr.getName()}.get()); } else { - scope.${genHelper.getPlainSetter(attr)}Absent(); + scope.${setter}Absent(); } <#else> - scope.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, scopeJson)); + scope.${setter}(deserialize${attr.getName()?cap_first}(scope, scopeJson)); diff --git a/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeScope.ftl b/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeScope.ftl index 2edbddd61f..1d967dd612 100644 --- a/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeScope.ftl +++ b/monticore-generator/src/main/resources/_symboltable/serialization/scopeDeSer/DeserializeScope.ftl @@ -9,15 +9,18 @@ ${tc.signature("symTabMill", "scopeClass", "scopeRuleAttrList")} scope.setExportingSymbols(true); <#list scopeRuleAttrList as attr> - <#if genHelper.isOptional(attr.getMCType())> + <#assign setter = genHelper.getPlainSetter(attr)> + <#if genHelper.shouldHaveSupplier(attr)> + scope.${setter}Supplier(deserialize${attr.getName()?cap_first}(scope, scopeJson)); + <#elseif genHelper.isOptional(attr.getMCType())> ${attr.printType()} _${attr.getName()} = deserialize${attr.getName()?cap_first}(scope, scopeJson); if (_${attr.getName()}.isPresent()) { - scope.${genHelper.getPlainSetter(attr)}(_${attr.getName()}.get()); + scope.${setter}(_${attr.getName()}.get()); } else { - scope.${genHelper.getPlainSetter(attr)}Absent(); + scope.${setter}Absent(); } <#else> - scope.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, scopeJson)); + scope.${setter}(deserialize${attr.getName()?cap_first}(scope, scopeJson)); diff --git a/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl b/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl index 4ddef86ab3..1a20fa832b 100644 --- a/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl +++ b/monticore-generator/src/main/resources/_symboltable/serialization/symbolDeSer/Deserialize4SymbolDeSer.ftl @@ -21,16 +21,16 @@ ${tc.signature("symTabMill", "symbolFullName", "symbolSimpleName","symbolRuleAtt } <#list symbolRuleAttribute as attr> - <#if !genHelper.shouldHaveSupplier(attr)> - <#if genHelper.isOptional(attr.getMCType())> - if (deserialize${attr.getName()?cap_first}(symbolJson).isPresent()) { - builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson).get()); - } else { - builder.${genHelper.getPlainSetter(attr)}Absent(); - } - <#else> - builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson)); - + <#if genHelper.shouldHaveSupplier(attr)> + builder.${genHelper.getPlainSetter(attr)}Supplier(deserialize${attr.getName()?cap_first}(scope, symbolJson)); + <#elseif genHelper.isOptional(attr.getMCType())> + if (deserialize${attr.getName()?cap_first}(symbolJson).isPresent()) { + builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson).get()); + } else { + builder.${genHelper.getPlainSetter(attr)}Absent(); + } + <#else> + builder.${genHelper.getPlainSetter(attr)}(deserialize${attr.getName()?cap_first}(scope, symbolJson)); @@ -50,12 +50,5 @@ ${tc.signature("symTabMill", "symbolFullName", "symbolSimpleName","symbolRuleAtt ${symbolFullName} symbol = builder.build(); - <#list symbolRuleAttribute as attr> - <#if genHelper.shouldHaveSupplier(attr)> - <#-- supplied attributes are not resolved immediately, so we store the supplied --> - symbol.${genHelper.getPlainSetter(attr)}Supplier(deserialize${attr.getName()?cap_first}(scope, symbolJson)); - - - deserializeAddons(symbol, symbolJson); return symbol; \ No newline at end of file diff --git a/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl b/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl index a874441c5b..ed0fc2e9de 100644 --- a/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl +++ b/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl @@ -3,15 +3,17 @@ ${tc.signature("symbolClassName", "attributes")} <#assign genHelper = glex.getGlobalVar("astHelper")> ${symbolClassName} symbol = new ${symbolClassName}(name); <#list attributes as attribute> -<#assign setter = genHelper.getPlainSetter(attribute)> -<#if genHelper.isOptional(attribute.getMCType())> - if (this.${attribute.getName()}.isPresent()) { - symbol.${setter}(this.${attribute.getName()}.get()); - } else { - symbol.${setter}Absent(); - } -<#else> - symbol.${setter}(this.${attribute.getName()}); - + <#assign setter = genHelper.getPlainSetter(attribute)> + <#if genHelper.isSupplier(attribute.getMCType())> + symbol.${setter}Supplier(this.${attribute.getName()}); + <#elseif genHelper.isOptional(attribute.getMCType())> + if (this.${attribute.getName()}.isPresent()) { + symbol.${setter}(this.${attribute.getName()}.get()); + } else { + symbol.${setter}Absent(); + } + <#else> + symbol.${setter}(this.${attribute.getName()}); + return symbol; diff --git a/monticore-test/it/src/main/grammars/mc/feature/scoperules/ScoperuleTest.mc4 b/monticore-test/it/src/main/grammars/mc/feature/scoperules/ScoperuleTest.mc4 index 8f7173c0d5..4381971431 100644 --- a/monticore-test/it/src/main/grammars/mc/feature/scoperules/ScoperuleTest.mc4 +++ b/monticore-test/it/src/main/grammars/mc/feature/scoperules/ScoperuleTest.mc4 @@ -34,8 +34,8 @@ grammar ScoperuleTest extends de.monticore.MCBasics, de.monticore.symbols.BasicS } symType:de.monticore.types.check.SymTypeExpression? method public void createSymType(){ - if(!symType.isPresent()){ - symType = Optional.of(de.monticore.types.check.SymTypeExpressionFactory.createPrimitive("double")); + if(!isPresentSymType()){ + setSymType(de.monticore.types.check.SymTypeExpressionFactory.createPrimitive("double")); } }; diff --git a/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 b/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 index 79ae74bcf8..28f593979e 100644 --- a/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 +++ b/monticore-test/it/src/main/grammars/mc/feature/symbolrules/SymbolruleTest.mc4 @@ -70,8 +70,8 @@ grammar SymbolruleTest extends de.monticore.MCBasics, de.monticore.symbols.Basic } symType:de.monticore.types.check.SymTypeExpression? method public void createSymType(){ - if(!symType.isPresent()){ - symType = Optional.of(de.monticore.types.check.SymTypeExpressionFactory.createPrimitive("double")); + if(!isPresentSymType()){ + setSymType(de.monticore.types.check.SymTypeExpressionFactory.createPrimitive("double")); } }; diff --git a/monticore-test/it/src/main/java/mc/feature/scoperules/scoperuletest/_symboltable/ScoperuleTestDeSer.java b/monticore-test/it/src/main/java/mc/feature/scoperules/scoperuletest/_symboltable/ScoperuleTestDeSer.java index c1b9cd9deb..c3f650e0ad 100644 --- a/monticore-test/it/src/main/java/mc/feature/scoperules/scoperuletest/_symboltable/ScoperuleTestDeSer.java +++ b/monticore-test/it/src/main/java/mc/feature/scoperules/scoperuletest/_symboltable/ScoperuleTestDeSer.java @@ -1,16 +1,18 @@ /* (c) https://github.com/MontiCore/monticore */ package mc.feature.scoperules.scoperuletest._symboltable; +import de.monticore.symboltable.serialization.json.JsonObject; import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionDeSer; import java.util.Optional; +import java.util.function.Supplier; public class ScoperuleTestDeSer extends ScoperuleTestDeSerTOP { @Override - public Optional deserializeSymType (de.monticore.symboltable.serialization.json.JsonObject scopeJson) { - return SymTypeExpressionDeSer.deserializeOptionalMember("symType",scopeJson); + public Supplier> deserializeSymType (JsonObject scopeJson) { + return () -> SymTypeExpressionDeSer.deserializeOptionalMember("symType",scopeJson); } @Override diff --git a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolrulelisttest/_symboltable/SymbolruleListTestDeSer.java b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolrulelisttest/_symboltable/SymbolruleListTestDeSer.java index b82a8f0572..1199440d19 100644 --- a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolrulelisttest/_symboltable/SymbolruleListTestDeSer.java +++ b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolrulelisttest/_symboltable/SymbolruleListTestDeSer.java @@ -1,13 +1,18 @@ /* (c) https://github.com/MontiCore/monticore */ package mc.feature.symbolrules.symbolrulelisttest._symboltable; +import de.monticore.symboltable.serialization.json.JsonObject; +import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionDeSer; +import java.util.List; +import java.util.function.Supplier; + public class SymbolruleListTestDeSer extends SymbolruleListTestDeSerTOP { @Override - public java.util.List deserializeSymTypes (de.monticore.symboltable.serialization.json.JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("symTypes", symbolJson); + public Supplier> deserializeSymTypes (JsonObject symbolJson) { + return () -> SymTypeExpressionDeSer.deserializeListMember("symTypes", symbolJson); } } diff --git a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/ITestSymbolDeSer.java b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/ITestSymbolDeSer.java index ca7f59bf4c..881281cf21 100644 --- a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/ITestSymbolDeSer.java +++ b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/ITestSymbolDeSer.java @@ -1,13 +1,18 @@ /* (c) https://github.com/MontiCore/monticore */ package mc.feature.symbolrules.symbolruletest._symboltable; +import de.monticore.symboltable.serialization.json.JsonObject; +import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionDeSer; +import java.util.List; +import java.util.function.Supplier; + public class ITestSymbolDeSer extends ITestSymbolDeSerTOP { @Override - public java.util.List deserializeSuperTypes (de.monticore.symboltable.serialization.json.JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); + public Supplier> deserializeSuperTypes (JsonObject symbolJson) { + return () -> SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); } } diff --git a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/SymbolruleTestDeSer.java b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/SymbolruleTestDeSer.java index 41099e0471..ea72025a7a 100644 --- a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/SymbolruleTestDeSer.java +++ b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/SymbolruleTestDeSer.java @@ -1,16 +1,18 @@ /* (c) https://github.com/MontiCore/monticore */ package mc.feature.symbolrules.symbolruletest._symboltable; +import de.monticore.symboltable.serialization.json.JsonObject; import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionDeSer; import java.util.Optional; +import java.util.function.Supplier; public class SymbolruleTestDeSer extends SymbolruleTestDeSerTOP { @Override - public java.util.Optional deserializeSymType (de.monticore.symboltable.serialization.json.JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeOptionalMember("symType", symbolJson); + public Supplier> deserializeSymType (JsonObject symbolJson) { + return () -> SymTypeExpressionDeSer.deserializeOptionalMember("symType", symbolJson); } @Override diff --git a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test1SymbolDeSer.java b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test1SymbolDeSer.java index 0b896d35c1..9dba4fe430 100644 --- a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test1SymbolDeSer.java +++ b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test1SymbolDeSer.java @@ -1,12 +1,17 @@ /* (c) https://github.com/MontiCore/monticore */ package mc.feature.symbolrules.symbolruletest._symboltable; +import de.monticore.symboltable.serialization.json.JsonObject; +import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionDeSer; +import java.util.List; +import java.util.function.Supplier; + public class Test1SymbolDeSer extends Test1SymbolDeSerTOP { - + @Override - public java.util.List deserializeSuperTypes (de.monticore.symboltable.serialization.json.JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); + public Supplier> deserializeSuperTypes (JsonObject symbolJson) { + return () -> SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); } } diff --git a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test2SymbolDeSer.java b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test2SymbolDeSer.java index fc2827479d..a1dfd73c8b 100644 --- a/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test2SymbolDeSer.java +++ b/monticore-test/it/src/main/java/mc/feature/symbolrules/symbolruletest/_symboltable/Test2SymbolDeSer.java @@ -1,13 +1,18 @@ /* (c) https://github.com/MontiCore/monticore */ package mc.feature.symbolrules.symbolruletest._symboltable; +import de.monticore.symboltable.serialization.json.JsonObject; +import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionDeSer; +import java.util.List; +import java.util.function.Supplier; + public class Test2SymbolDeSer extends Test2SymbolDeSerTOP { @Override - public java.util.List deserializeSuperTypes (de.monticore.symboltable.serialization.json.JsonObject symbolJson) { - return SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); + public Supplier> deserializeSuperTypes (JsonObject symbolJson) { + return () -> SymTypeExpressionDeSer.deserializeListMember("superTypes", symbolJson); } } From 3b7a68d27b46ec8915ac1186b3c3c0ee85e19fc7 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Mon, 21 Sep 2026 14:00:59 +0200 Subject: [PATCH 15/21] removed suppliers from SymTypeExpression desers --- .../codegen/cd2java/AbstractService.java | 31 ++++++++----- .../TypeDispatcherDecorator.java | 7 +-- .../_symboltable/FunctionSymbol.java | 8 +--- .../_symboltable/VariableSymbol.java | 8 +--- .../compsymbols/_symboltable/PortSymbol.java | 4 +- .../monticore/types/check/SymTypeArray.java | 7 +-- .../types/check/SymTypeExpressionFactory.java | 46 +++++++++++++++---- .../types/check/SymTypeOfGenerics.java | 9 +--- .../types/check/SymTypeOfGenericsDeSer.java | 8 +--- .../monticore/types/check/SymTypeOfNull.java | 4 +- .../types/check/SymTypeOfObject.java | 3 -- .../types/check/SymTypeOfObjectDeSer.java | 6 +-- .../types/check/SymTypeVariableDeSer.java | 6 +-- .../de/monticore/types/check/SymTypeVoid.java | 4 +- 14 files changed, 77 insertions(+), 74 deletions(-) diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/AbstractService.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/AbstractService.java index 0075980274..87ef53254a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/AbstractService.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/AbstractService.java @@ -21,7 +21,6 @@ import de.monticore.symbols.basicsymbols._symboltable.DiagramSymbol; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.ImportStatement; import de.monticore.types.MCTypeFacade; import de.monticore.types.check.SymTypeExpression; @@ -169,27 +168,35 @@ public List getAllSuperClassesTransitive(ASTCDClass astcdClass) { protected List getAllSuperClassesTransitive(TypeSymbol cdTypeSymbol) { List superSymbolList = new ArrayList<>(); if (cdTypeSymbol.isPresentSuperClass()) { - TypeSymbol superSymbol = cdTypeSymbol.getSuperClass().getTypeInfo(); - if (superSymbol instanceof TypeSymbolSurrogate) { - if (!((TypeSymbolSurrogate) superSymbol).checkLazyLoadDelegate()) { - return superSymbolList; - } - superSymbol = ((TypeSymbolSurrogate) superSymbol).lazyLoadDelegate(); + Optional superSymbol = resolveTypeInfo(cdTypeSymbol.getSuperClass()); + if (superSymbol.isEmpty()) { + return superSymbolList; } - - superSymbolList.add(superSymbol); - superSymbolList.addAll(getAllSuperClassesTransitive(superSymbol)); + superSymbolList.add(superSymbol.get()); + superSymbolList.addAll(getAllSuperClassesTransitive(superSymbol.get())); } return superSymbolList; } + public Optional resolveTypeInfo(SymTypeExpression symType) { + if (!symType.hasTypeInfo()) { + return Optional.empty(); + } + TypeSymbol typeInfo = symType.getTypeInfo(); + if (typeInfo.getEnclosingScope() == null) { + return Optional.of(typeInfo); + } + return typeInfo.getEnclosingScope().resolveType(typeInfo.getName()); + } + public List getAllSuperInterfacesTransitive(TypeSymbol cdTypeSymbol) { List superSymbolList = new ArrayList<>(); List localSuperInterfaces = Lists.newArrayList(); cdTypeSymbol.getSuperTypesList().stream() .filter(s -> !isTFInterface(s)) - .filter(s -> ((TypeSymbolSurrogate)s.getTypeInfo()).checkLazyLoadDelegate()) - .map(s -> ((TypeSymbolSurrogate)s.getTypeInfo()).lazyLoadDelegate()) + .map(this::resolveTypeInfo) + .filter(Optional::isPresent) + .map(Optional::get) .forEach(t -> {if(t instanceof CDTypeSymbol && ((CDTypeSymbol)t).isIsInterface()) localSuperInterfaces.add((CDTypeSymbol) t);}); for (CDTypeSymbol superInterface : localSuperInterfaces) { superSymbolList.add(createASTFullName(superInterface)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/typedispatcher/TypeDispatcherDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/typedispatcher/TypeDispatcherDecorator.java index 1d21f6dc02..75b434c285 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/typedispatcher/TypeDispatcherDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/typedispatcher/TypeDispatcherDecorator.java @@ -15,11 +15,11 @@ import de.monticore.generating.templateengine.StringHookPoint; import de.monticore.generating.templateengine.TemplateHookPoint; import de.monticore.symbols.basicsymbols._symboltable.DiagramSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.types.MCTypeFacade; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY; @@ -254,8 +254,9 @@ protected List createHandleMethods(List attributeNam protected List getSuperTypes(CDTypeSymbol typeSymbol) { return typeSymbol.getSuperTypesList() .stream() - .filter(s -> ((TypeSymbolSurrogate) s.getTypeInfo()).checkLazyLoadDelegate()) - .map(s -> ((TypeSymbolSurrogate) s.getTypeInfo()).lazyLoadDelegate()) + .map(visitorService::resolveTypeInfo) + .filter(Optional::isPresent) + .map(Optional::get) .filter(t -> t instanceof CDTypeSymbol) .map(s -> visitorService.createASTFullName((CDTypeSymbol) s)) .collect(Collectors.toList()); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java index a8c74c9ab3..9182126eb6 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java @@ -71,15 +71,9 @@ public List getParameterList(){ public void replaceTypeVariables(Map replaceMap){ //return type SymTypeExpression type = this.getType(); - TypeSymbol realTypeInfo; - TypeSymbol typeInfo = type.isTypeVariable() ? + TypeSymbol realTypeInfo = type.isTypeVariable() ? type.asTypeVariable().getTypeVarSymbol() : type.getTypeInfo(); - if(typeInfo instanceof TypeSymbolSurrogate){ - realTypeInfo = ((TypeSymbolSurrogate) type.getTypeInfo()).lazyLoadDelegate(); - }else{ - realTypeInfo = typeInfo; - } if(type.isTypeVariable() && realTypeInfo instanceof TypeVarSymbol){ Optional typeVar = replaceMap.keySet().stream().filter(t -> t.getName().equals(realTypeInfo.getName())).findAny(); typeVar.ifPresent(typeVarSymbol -> this.setType(replaceMap.get(typeVarSymbol))); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java index 3fa23d4911..c64466ceb2 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java @@ -36,15 +36,9 @@ public VariableSymbol deepClone(){ public void replaceTypeVariables(Map replaceMap){ //return type SymTypeExpression returnType = this.getType(); - TypeSymbol realTypeInfo; - TypeSymbol typeInfo = returnType.isTypeVariable() ? + TypeSymbol realTypeInfo = returnType.isTypeVariable() ? returnType.asTypeVariable().getTypeVarSymbol() : returnType.getTypeInfo(); - if(typeInfo instanceof TypeSymbolSurrogate){ - realTypeInfo = ((TypeSymbolSurrogate) returnType.getTypeInfo()).lazyLoadDelegate(); - }else{ - realTypeInfo = typeInfo; - } if(returnType.isTypeVariable() && realTypeInfo instanceof TypeVarSymbol){ Optional typeVar = replaceMap.keySet().stream().filter(t -> t.getName().equals(realTypeInfo.getName())).findAny(); typeVar.ifPresent(typeVarSymbol -> this.setType(replaceMap.get(typeVarSymbol))); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java index e100ed0580..615fc8cd38 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java @@ -3,7 +3,6 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.types.check.SymTypeExpression; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -50,8 +49,7 @@ public void setType(@NonNull SymTypeExpression type) { } public TypeSymbol getTypeInfo() { - return this.getType().getTypeInfo() instanceof TypeSymbolSurrogate ? - ((TypeSymbolSurrogate) this.getType().getTypeInfo()).lazyLoadDelegate() : this.getType().getTypeInfo(); + return this.getType().getTypeInfo(); } @Override diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeArray.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeArray.java index 07b874dba0..1a794a671b 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeArray.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeArray.java @@ -3,7 +3,6 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.types3.ISymTypeVisitor; import de.se_rwth.commons.logging.Log; @@ -98,11 +97,9 @@ public void setArgument(SymTypeExpression argument) { @Override public SymTypeArray deepClone() { //to support deprecated code: + // (hasTypeInfo() is deliberately false for arrays, check the field) if(typeSymbol != null) { - TypeSymbol typeSymbol = new TypeSymbolSurrogate(this.typeSymbol.getName()); - typeSymbol.setEnclosingScope(this.typeSymbol.getEnclosingScope()); - return new SymTypeArray(typeSymbol, - this.dim, this.argument.deepClone()); + return new SymTypeArray(this.typeSymbol, this.dim, this.argument.deepClone()); } else { return new SymTypeArray(getArgument().deepClone(), getDim()); diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index ad8f2ed1a8..b5bf0b14e8 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -9,12 +9,6 @@ import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; -import de.monticore.symbols.basicsymbols._symboltable.FunctionSymbol; -import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; -import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; -import de.monticore.symbols.basicsymbols._util.IBasicSymbolsTypeDispatcher; import de.se_rwth.commons.logging.Log; import java.util.ArrayList; @@ -167,6 +161,36 @@ public static SymTypeOfObject createTypeObjectViaSurrogate(String name, IBasicSy return new SymTypeOfObject(typeSymbol); } + + public static TypeSymbol resolveTypeSymbolOrLogError( + String name, IBasicSymbolsScope enclosingScope) { + Optional resolved = enclosingScope.resolveType(name); + if (resolved.isPresent()) { + return resolved.get(); + } + Log.error("0x893F62 Internal error: cannot resolve the type \"" + + name + "\" required by a SymTypeExpression!"); + TypeSymbol unresolved = new TypeSymbol(name); + unresolved.setEnclosingScope(enclosingScope); + unresolved.setFullName(name); + return unresolved; + } + + + public static TypeVarSymbol resolveTypeVarSymbolOrLogError( + String name, IBasicSymbolsScope enclosingScope) { + Optional resolved = enclosingScope.resolveTypeVar(name); + if (resolved.isPresent()) { + return resolved.get(); + } + Log.error("0x893F62 Internal error: cannot resolve the type variable \"" + + name + "\" required by a SymTypeExpression!"); + TypeVarSymbol unresolved = new TypeVarSymbol(name); + unresolved.setEnclosingScope(enclosingScope); + unresolved.setFullName(name); + return unresolved; + } + /** * for RegEx-types, e.g. 'R"gr(a|e)y"' */ @@ -216,8 +240,14 @@ public static SymTypeArray createTypeArray(TypeSymbol typeSymbol, int dim, @Deprecated(forRemoval = true) public static SymTypeArray createTypeArray(String name, IBasicSymbolsScope typeSymbolsScope, int dim, SymTypeExpression argument) { - TypeSymbol typeSymbol = new TypeSymbolSurrogate(name); - typeSymbol.setEnclosingScope(typeSymbolsScope); + + TypeSymbol typeSymbol = typeSymbolsScope.resolveType(name) + .orElseGet(() -> { + TypeSymbol unresolved = new TypeSymbol(name); + unresolved.setEnclosingScope(typeSymbolsScope); + unresolved.setFullName(name); + return unresolved; + }); return new SymTypeArray(typeSymbol, dim, argument); } diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenerics.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenerics.java index 7928acf443..47e2f18865 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenerics.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenerics.java @@ -3,7 +3,6 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; import de.monticore.types3.ISymTypeVisitor; import de.se_rwth.commons.logging.Log; @@ -278,13 +277,7 @@ else if (arguments.size() != typeVars.size()) { public void replaceTypeVariables(Map replaceMap) { for(int i = 0; i typeVar = replaceMap.keySet().stream().filter(t -> t.getName().equals(realTypeInfo.getName())).findAny(); if(typeVar.isPresent()){ diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java index 55d91d84eb..1fce3a3de4 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java @@ -3,7 +3,6 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -48,14 +47,11 @@ public SymTypeOfGenerics deserialize(JsonObject serialized, IBasicSymbolsScope e // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - TypeSymbolSurrogate typeSym = new TypeSymbolSurrogate(typeConstructorFullName); - typeSym.setEnclosingScope(enclosingScope); - List arguments = SymTypeExpressionDeSer .deserializeListMember(SERIALIZED_ARGUMENTS, serialized, enclosingScope); - return SymTypeExpressionFactory - .createGenerics(typeSym, arguments); + return SymTypeExpressionFactory.createGenerics(SymTypeExpressionFactory + .resolveTypeSymbolOrLogError(typeConstructorFullName, enclosingScope), arguments); } Log.error( "0x823F6 Internal error: Loading ill-structured SymTab: missing typeConstructorFullName of SymTypeOfGenerics " diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfNull.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfNull.java index 4b144e81db..cac344d594 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfNull.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfNull.java @@ -2,7 +2,7 @@ package de.monticore.types.check; import de.monticore.symbols.basicsymbols.BasicSymbolsMill; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.types3.ISymTypeVisitor; public class SymTypeOfNull extends SymTypeExpression { @@ -20,7 +20,7 @@ public class SymTypeOfNull extends SymTypeExpression { */ @Deprecated public SymTypeOfNull() { - typeSymbol = new TypeSymbolSurrogate(BasicSymbolsMill.NULL); + typeSymbol = new TypeSymbol(BasicSymbolsMill.NULL); typeSymbol.setEnclosingScope(BasicSymbolsMill.scope()); } diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java index 1bd0d40b18..8f0237bb3c 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java @@ -15,9 +15,6 @@ public class SymTypeOfObject extends SymTypeExpression { protected TypeSymbol typeSymbol; - /** - * Constructor: with a TypeSymbolSurrogate that contains the name and enclosingScope - */ public SymTypeOfObject(TypeSymbol typeSymbol) { Preconditions.checkNotNull(typeSymbol); diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java index e9b1406717..a40a83125d 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java @@ -3,7 +3,6 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -43,9 +42,8 @@ public SymTypeOfObject deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - TypeSymbolSurrogate typeSym = new TypeSymbolSurrogate(objName); - typeSym.setEnclosingScope(enclosingScope); - return SymTypeExpressionFactory.createTypeObject(typeSym); + return SymTypeExpressionFactory.createTypeObject(SymTypeExpressionFactory + .resolveTypeSymbolOrLogError(objName, enclosingScope)); } Log.error("0x823F4 Internal error: Cannot load \"" + serialized + "\" as SymTypeOfObject!"); diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java index 276e853dd5..647ebbd226 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java @@ -3,7 +3,6 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; -import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbolSurrogate; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -51,9 +50,8 @@ public SymTypeVariable deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior: enclosingScope = BasicSymbolsMill.globalScope(); } - TypeVarSymbolSurrogate typeVarSym = new TypeVarSymbolSurrogate(varName); - typeVarSym.setEnclosingScope(enclosingScope); - return SymTypeExpressionFactory.createTypeVariable(typeVarSym); + return SymTypeExpressionFactory.createTypeVariable(SymTypeExpressionFactory + .resolveTypeVarSymbolOrLogError(varName, enclosingScope)); } Log.error("0x823F5 Internal error: Cannot load \"" + serialized + "\" as SymTypeVariable!"); return null; diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVoid.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVoid.java index a044c0c654..399d85c3c8 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVoid.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVoid.java @@ -3,7 +3,7 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; -import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolSurrogate; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.types3.ISymTypeVisitor; public class SymTypeVoid extends SymTypeExpression { @@ -14,7 +14,7 @@ public class SymTypeVoid extends SymTypeExpression { */ @Deprecated public SymTypeVoid() { - typeSymbol = new TypeSymbolSurrogate(BasicSymbolsMill.VOID); + typeSymbol = new TypeSymbol(BasicSymbolsMill.VOID); typeSymbol.setEnclosingScope(BasicSymbolsMill.globalScope()); } From e02cd6dd1ea3e272fdcec6d57191eca1025d3461 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Mon, 21 Sep 2026 16:54:10 +0200 Subject: [PATCH 16/21] extracted duplicate code: from internal to normal supplier wrapping all shouldBeWrapped attributes avoiding double-wrapping internal supplier deep-clone now works with suppliers --- .../codegen/cd2java/DecorationHelper.java | 44 +++++++++++++------ .../BuilderListMutatorDecorator.java | 3 +- .../BuilderMandatoryMutatorDecorator.java | 6 +-- .../BuilderOptionalMutatorDecorator.java | 5 +-- .../InheritedBuilderListMutatorDecorator.java | 3 +- ...ritedBuilderMandatoryMutatorDecorator.java | 6 +-- ...eritedBuilderOptionalMutatorDecorator.java | 3 +- .../scope/ScopeClassDecorator.java | 7 ++- .../scope/ScopeInterfaceDecorator.java | 5 +-- .../SymTypeExpressionSerStrategy.java | 6 +-- .../symbol/SymbolBuilderDecorator.java | 8 +--- .../_symboltable/symbol/SymbolDecorator.java | 5 +-- .../methods/AccessAsSupplierTypes.java | 22 +++++++--- .../cd2java/methods/ListMethodDecorator.java | 2 +- .../methods/SpecificMethodDecorator.java | 2 +- .../accessor/ListAccessorDecorator.java | 7 +-- .../accessor/MandatoryAccessorDecorator.java | 6 +-- .../accessor/OptionalAccessorDecorator.java | 6 +-- .../methods/mutator/ListMutatorDecorator.java | 11 ++--- .../mutator/MandatoryMutatorDecorator.java | 7 +-- .../mutator/OptionalMutatorDecorator.java | 5 +-- .../builder/SupplierSetRaw4ASTBuilder.ftl | 8 +--- .../main/resources/methods/SupplierGet.ftl | 8 ++-- .../main/resources/methods/SupplierSetRaw.ftl | 8 +--- .../_symboltable/FunctionSymbol.java | 4 +- .../_symboltable/VariableSymbol.java | 7 ++- .../compsymbols/_symboltable/PortSymbol.java | 2 +- .../oosymbols/_symboltable/FieldSymbol.java | 7 +-- .../oosymbols/_symboltable/MethodSymbol.java | 5 ++- .../types/check/SymTypeExpressionFactory.java | 4 +- .../types/check/SymTypeOfObject.java | 1 - .../symboltable/ClearingMemorizer.java | 42 ++++++++++++++++++ .../symboltable/__internal__Supplier.java | 16 +++++-- 33 files changed, 163 insertions(+), 118 deletions(-) create mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index a2730be8e0..82b36979f6 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -9,6 +9,7 @@ import de.monticore.codegen.mc2cd.MC2CDStereotypes; import de.monticore.codegen.mc2cd.TransformationHelper; import de.monticore.generating.templateengine.GlobalExtensionManagement; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.generating.templateengine.HookPoint; import de.monticore.generating.templateengine.StringHookPoint; import de.monticore.symboltable.ISymbol; @@ -27,11 +28,13 @@ import de.se_rwth.commons.StringTransformations; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Optional; import static de.monticore.cd.codegen.CD2JavaTemplates.VALUE; import static de.monticore.codegen.cd2java._ast.ast_class.ASTConstants.AST_PREFIX; +import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes.STD_SUPPLIER_TYPE; import static de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes.SUPPLIER_TYPE; public class DecorationHelper extends MCBasicTypesHelper { @@ -105,19 +108,19 @@ public boolean isOptional(String type) { return "Optional".equals(Names.getSimpleName(type)); } - /** - * Checks whether the type is wrapped by the internal supplier type - */ + /** + * Checks whether the type is wrapped by the internal supplier type. + */ public boolean isSupplier(String type) { int index = type.indexOf('<'); if (index != -1) { type = type.substring(0, index); } - return Names.getSimpleName(SUPPLIER_TYPE).equals(Names.getSimpleName(type)); + return SUPPLIER_TYPE.equals(type); } // The ASTMCType overloads intentionally delegate to the String checks above instead of using - // instanceof: a single implementation, and no reliance on the concrete AST node (see PR #372 review). + // instanceof: a single implementation, and no reliance on the concrete AST node. public boolean isOptional(ASTMCType type) { return isOptional(type.printType()); } @@ -131,7 +134,7 @@ public boolean isSupplier(ASTMCType type) { } public boolean shouldHaveSupplier(ASTCDAttribute attribute) { - return de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes.shouldHaveSupplier(attribute); + return AccessAsSupplierTypes.shouldHaveSupplier(attribute); } public boolean isString(String type) { @@ -181,11 +184,8 @@ public String getSimpleNativeType(String nativeAttributeType) { */ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionManagement glex) { // For a wrapped attribute (Supplier) the default is derived from the unwrapped type X. - ASTMCType type = attribute.getMCType(); - boolean isSupplier = isSupplier(type); - if (isSupplier) { - type = getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); - } + boolean isSupplier = isSupplier(attribute.getMCType()); + ASTMCType type = unwrapSupplier(attribute.getMCType()); boolean isList = isList(type); String inner; @@ -231,7 +231,7 @@ public ASTMCTypeArgument getReferenceTypeOfOptional(ASTMCType type) { public ASTMCTypeArgument getReferenceTypeOfSupplier(ASTMCType type) { Preconditions.checkArgument(isSupplier(type)); - return ((ASTMCGenericType) type).getMCTypeArgumentList().get(0); + return ((ASTMCGenericType) type).getMCTypeArgumentList().getFirst(); } /** @@ -253,7 +253,7 @@ public ASTMCType createInternalSupplierTypeOf(ASTMCType inner) { public ASTMCType createStdSupplierTypeOf(ASTMCType inner) { ASTMCTypeArgument arg = MCSimpleGenericTypesMill .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); - return MCTypeFacade.getInstance().createBasicGenericTypeOf("java.util.function.Supplier", arg); + return MCTypeFacade.getInstance().createBasicGenericTypeOf(STD_SUPPLIER_TYPE, arg); } /** @@ -301,6 +301,24 @@ public ASTMCType unwrapSupplier(ASTMCType type) { return type; } + /** + * The type that generated code exposes for a supplied attribute: + * {@code __internal__Supplier} (or an unwrapped X) becomes {@code java.util.function.Supplier}, + * so the internal wrapper never leaks into the public API. + */ + public ASTMCType toPublicSupplierType(ASTMCType type) { + return createStdSupplierTypeOf(unwrapSupplier(type)); + } + + /** + * Wraps the type of every attribute that {@link #shouldHaveSupplier} selects into the internal supplier type. + */ + public void wrapSuppliers(Collection attributes) { + attributes.stream() + .filter(this::shouldHaveSupplier) + .forEach(a -> a.setMCType(createInternalSupplierTypeOf(a.getMCType()))); + } + /** * methods return correct getters or setters for a special attribut * needed in templates diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java index a037349824..deeaf50a5e 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java @@ -70,8 +70,7 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { @Override protected ASTCDMethod createSetListSupplierMethod(ASTCDAttribute ast) { String name = "set" + capitalizedAttributeNameWithOutS + "ListSupplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java index 192e67a523..f64d186175 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderMandatoryMutatorDecorator.java @@ -30,7 +30,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { String templateName = "_ast.builder.Set4ASTBuilder"; if (getDecorationHelper().isSupplier(ast.getMCType())) { attribute = ast.deepClone(); - attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); + attribute.setMCType(getDecorationHelper().unwrapSupplier(attribute.getMCType())); templateName = "_ast.builder.SupplierSet4ASTBuilder"; } @@ -43,9 +43,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { @Override protected ASTCDMethod createSupplierSetter(final ASTCDAttribute ast) { ASTCDAttribute attribute = ast.deepClone(); - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); - attribute.setMCType(supplierType); + attribute.setMCType(getDecorationHelper().toPublicSupplierType(ast.getMCType())); String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))) + "Supplier"; ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java index d52ae1fad1..b0ada5b6dd 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java @@ -35,7 +35,7 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String templateName; if (getDecorationHelper().isSupplier(type)) { templateName = "_ast.builder.opt.SupplierSet4ASTBuilderOpt"; - type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + type = getDecorationHelper().unwrapSupplier(type); } else { templateName = "_ast.builder.opt.Set4ASTBuilderOpt"; } @@ -52,8 +52,7 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { @Override protected ASTCDMethod createSupplierSetMethod(final ASTCDAttribute ast) { String name = String.format(SET, naiveAttributeName) + "Supplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java index ee706692b7..8c2c9ff321 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderListMutatorDecorator.java @@ -36,8 +36,7 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { @Override protected ASTCDMethod createSetListSupplierMethod(ASTCDAttribute ast) { String name = "set" + capitalizedAttributeNameWithOutS + "ListSupplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java index ea9f565c67..ac4310baaf 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderMandatoryMutatorDecorator.java @@ -27,7 +27,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { ASTCDAttribute attribute = ast; if (getDecorationHelper().isSupplier(ast.getMCType())) { attribute = ast.deepClone(); - attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); + attribute.setMCType(getDecorationHelper().unwrapSupplier(attribute.getMCType())); } String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); @@ -38,9 +38,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { @Override protected ASTCDMethod createSupplierSetter(final ASTCDAttribute ast) { ASTCDAttribute attribute = ast.deepClone(); - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); - attribute.setMCType(supplierType); + attribute.setMCType(getDecorationHelper().toPublicSupplierType(ast.getMCType())); String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))) + "Supplier"; ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), builderType, name, this.getCDParameterFacade().createParameters(attribute)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java index 09079228c6..91d1869e8d 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java @@ -41,8 +41,7 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { @Override protected ASTCDMethod createSupplierSetMethod(final ASTCDAttribute ast) { String name = String.format(SET, naiveAttributeName) + "Supplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java index c783c1c31d..6c1c3e90e3 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java @@ -17,7 +17,6 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; -import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -96,9 +95,9 @@ public ASTCDClass decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilationUnit .flatMap(List::stream) .map(ASTCDAttribute::deepClone) .collect(Collectors.toList()); - scopeRuleAttributeList.stream() - .filter(AccessAsSupplierTypes::shouldHaveSupplier) - .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); + + // Wrap selected scoperule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later + getDecorationHelper().wrapSuppliers(scopeRuleAttributeList); scopeRuleAttributeList .forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java index abf9a25095..cc4da1297e 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java @@ -15,7 +15,6 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; -import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -95,9 +94,7 @@ public ASTCDInterface decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilation .flatMap(List::stream) .map(ASTCDAttribute::deepClone) .collect(Collectors.toList()); - scopeRuleAttributes.stream() - .filter(AccessAsSupplierTypes::shouldHaveSupplier) - .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); + getDecorationHelper().wrapSuppliers(scopeRuleAttributes); List scopeRuleMethodList = scopeInput.deepClone().getCDDefinition().getCDClassesList() .stream() diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java index 2633e1850f..4930bbfd27 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java @@ -30,16 +30,16 @@ public HookPoint getListSerialHook(String 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)); + return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer<>(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); } @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)); + return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer<>(() -> 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)); + return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer<>(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeListMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); } } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java index f36c504b83..1737ed7acb 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java @@ -12,7 +12,6 @@ import de.monticore.codegen.cd2java._ast.builder.BuilderDecorator; import de.monticore.codegen.cd2java._ast.builder.buildermethods.BuilderMutatorMethodDecorator; import de.monticore.codegen.cd2java._symboltable.SymbolTableService; -import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.HookPoint; import de.monticore.generating.templateengine.StringHookPoint; @@ -75,11 +74,8 @@ public ASTCDClass decorate(final ASTCDClass symbolClass) { defaultAttrs.add(spannedScopeAttr); } } - - decoratedSymbolClass.getCDAttributeList().stream() - .filter(AccessAsSupplierTypes::shouldHaveSupplier) - .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); - + // Wrap selected attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later + getDecorationHelper().wrapSuppliers(decoratedSymbolClass.getCDAttributeList()); builderDecorator.setPrintBuildMethodTemplate(false); ASTCDClass symbolBuilder = builderDecorator.decorate(decoratedSymbolClass); builderDecorator.setPrintBuildMethodTemplate(true); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index 466a175994..a0ff9251a3 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -14,7 +14,6 @@ import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorConstants; import de.monticore.codegen.cd2java._visitor.VisitorService; -import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.StringHookPoint; @@ -93,9 +92,7 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { .collect(Collectors.toList()); // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later - symbolRuleAttributes.stream() - .filter(AccessAsSupplierTypes::shouldHaveSupplier) - .forEach(a -> a.setMCType(getDecorationHelper().createInternalSupplierTypeOf(a.getMCType()))); + getDecorationHelper().wrapSuppliers(symbolRuleAttributes); symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); List symbolRuleAttributeMethods = symbolRuleAttributes diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java index 89fe31bc47..1004c7e54c 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -3,21 +3,26 @@ import de.monticore.cdbasis._ast.ASTCDAttribute; -import java.util.Arrays; +import java.util.Set; /** - * Some attributes in symbolrules must be decorated with a supplier, since they might not be known immediatly during the deserialization. - * + * Some attributes in symbolrules must be decorated with a supplier, since they might not be known immediately during the deserialization. + *

* This class contains what those types are */ -public class AccessAsSupplierTypes { +public final class AccessAsSupplierTypes { /** * Fully qualified name of the wrapper type used for lazily resolved attributes. */ public static final String SUPPLIER_TYPE = "de.monticore.symboltable.__internal__Supplier"; - private static final String[] SUPPLYLIST = { + /** + * Fully qualified name of the public supplier type exposed by generated getters and setters. + */ + public static final String STD_SUPPLIER_TYPE = "java.util.function.Supplier"; + + private static final Set SUPPLIED_TYPES = Set.of( "de.monticore.types.check.SymTypeExpression", "java.util.List", "java.util.Optional", @@ -28,14 +33,17 @@ public class AccessAsSupplierTypes { "java.util.Optional", "List", "Optional" - }; + ); + + private AccessAsSupplierTypes() { + } /** * @param type the printed attribute type * @return whether an attribute of this type should be wrapped in / accessed via a {@code Supplier} */ public static boolean shouldHaveSupplier(String type) { - return Arrays.asList(SUPPLYLIST).contains(type); + return SUPPLIED_TYPES.contains(type); } public static boolean shouldHaveSupplier(ASTCDAttribute attribute) { diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java index f14d4298ec..4067b939b0 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/ListMethodDecorator.java @@ -87,7 +87,7 @@ public String getAttributeType(ASTCDAttribute attribute) { if (getDecorationHelper().isSupplier(type)) { // a wrapped list attribute has the shape Supplier> -> unwrap to List before extracting X - type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + type = getDecorationHelper().unwrapSupplier(type); } return getTypeArgumentFromListType(type); } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java index fc7f1c58ff..64e7dcd763 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/SpecificMethodDecorator.java @@ -51,7 +51,7 @@ protected AbstractCreator> determineMethodDeco // If the type is wrapped (supplier), unwrap for determination ASTMCType type = ast.getMCType(); if (getDecorationHelper().isSupplier(type)) { - type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + type = getDecorationHelper().unwrapSupplier(type); } if (getMCTypeFacade().isBooleanType(type)) { diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java index f9eb92f88d..1c9fddeb29 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java @@ -6,11 +6,13 @@ import de.monticore.codegen.cd2java.methods.ListMethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import java.util.Arrays; import java.util.List; import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY; +import static de.monticore.cd.facade.CDModifier.PUBLIC; public class ListAccessorDecorator extends ListMethodDecorator { @@ -66,10 +68,9 @@ protected ASTCDMethod createGetListMethod(ASTCDAttribute ast) { protected ASTCDMethod createGetListSupplierMethod(ASTCDAttribute ast) { String name = "get" + capitalizedAttributeNameWithOutS + "ListSupplier"; - de.monticore.types.mcbasictypes._ast.ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDMethod method = this.getCDMethodFacade().createMethod( - de.monticore.cd.facade.CDModifier.PUBLIC.build(), supplierType, name); + PUBLIC.build(), supplierType, name); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierGetRaw", ast)); return method; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index 51a536c68a..53c555a840 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import static de.monticore.cd.facade.CDModifier.PUBLIC; @@ -50,7 +49,7 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)) { // The Supplier is hidden from the user. The getter has to expose the unwrapped type (Supplier -> X) - type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + type = getDecorationHelper().unwrapSupplier(type); templateName = "methods.SupplierGet"; } else { templateName = "methods.Get"; @@ -63,8 +62,7 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { protected ASTCDMethod createSupplierGetter(final ASTCDAttribute ast) { String name = String.format(GET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))) + "Supplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), supplierType, name); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierGetRaw", ast)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index 1fa6baa189..8c967ceead 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -11,7 +11,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import static de.monticore.cd.facade.CDModifier.PUBLIC; @@ -56,7 +55,7 @@ protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)){ templateName = "methods.opt.SupplierGet4Opt"; - type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + type = getDecorationHelper().unwrapSupplier(type); } else { templateName = "methods.opt.Get4Opt"; } @@ -70,8 +69,7 @@ protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { protected ASTCDMethod createSupplierGetMethod(final ASTCDAttribute ast) { String name = String.format(GET, naiveAttributeName) + "Supplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), supplierType, name); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierGetRaw", ast)); return method; diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java index e376244771..69441b9ed8 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java @@ -1,16 +1,19 @@ /* (c) https://github.com/MontiCore/monticore */ package de.monticore.codegen.cd2java.methods.mutator; +import de.monticore.cd4codebasis._ast.ASTCDParameter; import de.monticore.cdbasis._ast.ASTCDAttribute; import de.monticore.cd4codebasis._ast.ASTCDMethod; import de.monticore.codegen.cd2java.methods.ListMethodDecorator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import java.util.Arrays; import java.util.List; import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY; +import static de.monticore.cd.facade.CDModifier.PUBLIC; public class ListMutatorDecorator extends ListMethodDecorator { @@ -61,12 +64,10 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { protected ASTCDMethod createSetListSupplierMethod(ASTCDAttribute ast) { String name = "set" + capitalizedAttributeNameWithOutS + "ListSupplier"; - de.monticore.types.mcbasictypes._ast.ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); - de.monticore.cd4codebasis._ast.ASTCDParameter parameter = + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); + ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); - ASTCDMethod method = this.getCDMethodFacade().createMethod( - de.monticore.cd.facade.CDModifier.PUBLIC.build(), name, parameter); + ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierSetRaw", ast)); return method; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java index d155ede680..cb10708529 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/MandatoryMutatorDecorator.java @@ -6,7 +6,6 @@ import de.monticore.codegen.cd2java.AbstractCreator; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; -import de.monticore.types.mcbasictypes._ast.ASTMCType; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -39,7 +38,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { if (getDecorationHelper().isSupplier(ast.getMCType())) { // expose the unwrapped type (Supplier -> X) in the setter parameter; the Supplier stays hidden attribute = ast.deepClone(); - attribute.setMCType(getDecorationHelper().getReferenceTypeOfSupplier(attribute.getMCType()).getMCTypeOpt().get()); + attribute.setMCType(getDecorationHelper().unwrapSupplier(attribute.getMCType())); templateName = "methods.SupplierSet"; } @@ -52,9 +51,7 @@ protected ASTCDMethod createSetter(final ASTCDAttribute ast) { protected ASTCDMethod createSupplierSetter(final ASTCDAttribute ast) { ASTCDAttribute attribute = ast.deepClone(); - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); - attribute.setMCType(supplierType); + attribute.setMCType(getDecorationHelper().toPublicSupplierType(ast.getMCType())); String name = String.format(SET, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(attribute.getName()))) + "Supplier"; ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, this.getCDParameterFacade().createParameters(attribute)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index f9b8c77f59..6d56912897 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -47,7 +47,7 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { String templateName; if (getDecorationHelper().isSupplier(type)){ templateName = "methods.opt.SupplierSet4Opt"; - type = getDecorationHelper().getReferenceTypeOfSupplier(type).getMCTypeOpt().get(); + type = getDecorationHelper().unwrapSupplier(type); } else { templateName = "methods.opt.Set4Opt"; } @@ -61,8 +61,7 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { protected ASTCDMethod createSupplierSetMethod(final ASTCDAttribute ast) { String name = String.format(SET, naiveAttributeName) + "Supplier"; - ASTMCType supplierType = getMCTypeFacade().createBasicGenericTypeOf( - "java.util.function.Supplier", getDecorationHelper().getReferenceTypeOfSupplier(ast.getMCType())); + ASTMCType supplierType = getDecorationHelper().toPublicSupplierType(ast.getMCType()); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(supplierType, ast.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint("methods.SupplierSetRaw", ast)); diff --git a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl index 4370f452a1..0ce770786f 100644 --- a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl +++ b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl @@ -1,12 +1,6 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -<#assign genHelper = glex.getGlobalVar("astHelper")> ${defineHookPoint("Setter:Before")} -<#-- avoid double-wrapping when the caller passes back an already-wrapped supplier --> -if (${attribute.getName()} instanceof de.monticore.symboltable.__internal__Supplier) { - this.${attribute.getName()} = (${genHelper.printType(attribute.getMCType())}) ${attribute.getName()}; -} else { - this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); -} +this.${attribute.getName()} = de.monticore.symboltable.__internal__Supplier.of(${attribute.getName()}); ${defineHookPoint("Setter:After")} return this.realBuilder; diff --git a/monticore-generator/src/main/resources/methods/SupplierGet.ftl b/monticore-generator/src/main/resources/methods/SupplierGet.ftl index 0e92487df9..e09f4bc2d6 100644 --- a/monticore-generator/src/main/resources/methods/SupplierGet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierGet.ftl @@ -1,7 +1,7 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -var __value = this.${attribute.getName()}.get(); -if (__value == null) { -Log.info("Value of '${attribute.getName()}' is not available yet.", "get${attribute.getName()}"); +var value = this.${attribute.getName()}.get(); +if (value == null) { + Log.info("Value of '${attribute.getName()}' is not available yet.", "get${attribute.getName()}"); } -return __value; +return value; diff --git a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl index a5b930ce41..947870a83a 100644 --- a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl @@ -1,11 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -<#assign genHelper = glex.getGlobalVar("astHelper")> ${defineHookPoint("Setter:Before")} -<#-- avoid double-wrapping when the caller passes back an already-wrapped supplier --> -if (${attribute.getName()} instanceof de.monticore.symboltable.__internal__Supplier) { - this.${attribute.getName()} = (${genHelper.printType(attribute.getMCType())}) ${attribute.getName()}; -} else { - this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); -} +this.${attribute.getName()} = de.monticore.symboltable.__internal__Supplier.of(${attribute.getName()}); ${defineHookPoint("Setter:After")} diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java index 9182126eb6..f51ddc48d2 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java @@ -2,6 +2,7 @@ package de.monticore.symbols.basicsymbols._symboltable; import com.google.common.collect.Lists; +import de.monticore.symboltable.ClearingMemorizer; import de.monticore.symboltable.modifiers.AccessModifier; import de.monticore.types.check.SymTypeExpression; import de.monticore.types.check.SymTypeExpressionFactory; @@ -21,7 +22,8 @@ public FunctionSymbol(String name){ public FunctionSymbol deepClone(){ FunctionSymbol clone = new FunctionSymbol(name); - clone.setType(this.getType().deepClone()); + // keep the type lazy + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); clone.setIsElliptic(this.isIsElliptic()); clone.setEnclosingScope(this.enclosingScope); clone.setFullName(this.fullName); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java index c64466ceb2..ab02cd9941 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java @@ -1,6 +1,7 @@ /* (c) https://github.com/MontiCore/monticore */ package de.monticore.symbols.basicsymbols._symboltable; +import de.monticore.symboltable.ClearingMemorizer; import de.monticore.symboltable.modifiers.AccessModifier; import de.monticore.types.check.SymTypeExpression; import de.se_rwth.commons.logging.Log; @@ -22,10 +23,8 @@ public VariableSymbol deepClone(){ if(isPresentAstNode()) { clone.setAstNode(this.getAstNode()); } - SymTypeExpression t = getType(); - if(t!=null){ - clone.setType(t.deepClone()); - } + // keep the type lazy + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); return clone; } diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java index 615fc8cd38..dd7e4a4220 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/PortSymbol.java @@ -34,7 +34,7 @@ protected PortSymbol(String name, public boolean isTypePresent() { // type is not an optional, so we resolve it here to check if it is null - return super.type.get() != null; + return getTypeSupplier().get() != null; } public SymTypeExpression getType() { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java index d29dbee6f2..8c39fc311b 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java @@ -1,7 +1,9 @@ /* (c) https://github.com/MontiCore/monticore */ package de.monticore.symbols.oosymbols._symboltable; +import de.monticore.symboltable.ClearingMemorizer; import de.monticore.symboltable.modifiers.*; +import de.monticore.types.check.SymTypeExpression; import java.util.ArrayList; import java.util.List; @@ -34,9 +36,8 @@ public FieldSymbol deepClone(){ if(isPresentAstNode()) { clone.setAstNode(this.getAstNode()); } - if(getType()!=null){ - clone.setType(this.getType().deepClone()); - } + // keep the type lazy + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); return clone; } diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java index ae7afb1d41..1d426e84a4 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java @@ -2,7 +2,9 @@ package de.monticore.symbols.oosymbols._symboltable; import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; +import de.monticore.symboltable.ClearingMemorizer; import de.monticore.symboltable.modifiers.*; +import de.monticore.types.check.SymTypeExpression; import java.util.ArrayList; import java.util.List; @@ -18,7 +20,8 @@ public MethodSymbol(String name) { */ public MethodSymbol deepClone() { MethodSymbol clone = new MethodSymbol(name); - clone.setType(getType().deepClone()); + // keep the type lazy + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); clone.setEnclosingScope(this.enclosingScope); clone.setFullName(this.fullName); clone.setIsConstructor(this.isConstructor); diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index b5bf0b14e8..2ec4438534 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -168,7 +168,7 @@ public static TypeSymbol resolveTypeSymbolOrLogError( if (resolved.isPresent()) { return resolved.get(); } - Log.error("0x893F62 Internal error: cannot resolve the type \"" + Log.error("0x893F63 Internal error: cannot resolve the type \"" + name + "\" required by a SymTypeExpression!"); TypeSymbol unresolved = new TypeSymbol(name); unresolved.setEnclosingScope(enclosingScope); @@ -183,7 +183,7 @@ public static TypeVarSymbol resolveTypeVarSymbolOrLogError( if (resolved.isPresent()) { return resolved.get(); } - Log.error("0x893F62 Internal error: cannot resolve the type variable \"" + Log.error("0x893F64 Internal error: cannot resolve the type variable \"" + name + "\" required by a SymTypeExpression!"); TypeVarSymbol unresolved = new TypeVarSymbol(name); unresolved.setEnclosingScope(enclosingScope); diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java index 8f0237bb3c..107aaa6eb6 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObject.java @@ -4,7 +4,6 @@ import com.google.common.base.Preconditions; import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; import de.monticore.types3.ISymTypeVisitor; -import de.se_rwth.commons.logging.Log; /** * An objectType is a full qualified class name. diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java b/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java new file mode 100644 index 0000000000..66468c90d1 --- /dev/null +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java @@ -0,0 +1,42 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.symboltable; + +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Evaluates the wrapped supplier at most once and caches the result. Afterwards the + * supplier is released (and with it everything it captured, e.g. the JSON it deserializes from). + */ +public class ClearingMemorizer implements Supplier { + + private Supplier supplier; + + private T cache; + + public ClearingMemorizer(Supplier supplier) { + this.supplier = supplier; + } + + /** + * Lazily applies the mapper to the value of the source, evaluated at most once. + * A null value of the source stays null. Nothing is evaluated until the result is requested, + * e.g. to copy a not-yet-resolvable attribute of a symbol without forcing it. + */ + public static Supplier map(Supplier source, Function mapper) { + return new ClearingMemorizer<>(() -> { + T value = source.get(); + return value == null ? null : mapper.apply(value); + }); + } + + @Override + public T get() { + if (supplier != null) { + // a null result is cached as well + cache = supplier.get(); + supplier = null; + } + return cache; + } +} diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java index 6d2aa5931e..eb0819cd35 100644 --- a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java @@ -7,16 +7,26 @@ * Internal marker wrapper used by generated symbol classes for symbolrule attributes whose value * may not be resolvable yet (see {@code AccessAsSupplierTypes} in the generator). *

- * A dedicated type (instead of a plain {@link Supplier}) is required in case someone wants to actually return a supplier + * A dedicated type (instead of a plain {@link Supplier}) is required in case someone wants to actually return a supplier. */ -public class __internal__Supplier implements Supplier { +public final class __internal__Supplier implements Supplier { - protected final Supplier supplier; + private final Supplier supplier; public __internal__Supplier(Supplier supplier) { this.supplier = supplier; } + /** + * Wraps the supplier, unless it already is wrapped (avoids double-wrapping). + */ + public static __internal__Supplier of(Supplier supplier) { + if (supplier instanceof __internal__Supplier wrapped) { + return wrapped; + } + return new __internal__Supplier<>(supplier); + } + @Override public T get() { return supplier.get(); From 22c73777fae78c0247e916a41dba6bed65a2ca01 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Tue, 22 Sep 2026 12:31:28 +0200 Subject: [PATCH 17/21] make all the decorator look the same (don't want to pull out a function because we have multiple return types) made ClearingMemorizer.map more general --- .../BuilderListMutatorDecorator.java | 7 ++++--- .../BuilderOptionalMutatorDecorator.java | 13 ++++++------- .../InheritedBuilderOptionalMutatorDecorator.java | 5 ++++- .../methods/accessor/ListAccessorDecorator.java | 4 +--- .../accessor/MandatoryAccessorDecorator.java | 4 +--- .../accessor/OptionalAccessorDecorator.java | 14 +++++--------- .../methods/mutator/ListMutatorDecorator.java | 4 +--- .../methods/mutator/OptionalMutatorDecorator.java | 14 +++++--------- .../basicsymbols/_symboltable/FunctionSymbol.java | 2 +- .../basicsymbols/_symboltable/VariableSymbol.java | 2 +- .../oosymbols/_symboltable/FieldSymbol.java | 2 +- .../oosymbols/_symboltable/MethodSymbol.java | 2 +- .../monticore/symboltable/ClearingMemorizer.java | 9 +++------ 13 files changed, 34 insertions(+), 48 deletions(-) diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java index deeaf50a5e..6effd93ee6 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java @@ -60,9 +60,10 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); method.setMCReturnType(returnType); - String templateName = getDecorationHelper().isSupplier(ast.getMCType()) - ? "_ast.builder.SupplierSet4ASTBuilder" - : "_ast.builder.Set4ASTBuilder"; + String templateName = "_ast.builder.Set4ASTBuilder"; + if (getDecorationHelper().isSupplier(ast.getMCType())) { + templateName = "_ast.builder.SupplierSet4ASTBuilder"; + } this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); return method; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java index b0ada5b6dd..2826303fd6 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderOptionalMutatorDecorator.java @@ -32,12 +32,10 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); ASTMCType type = attribute.getMCType().deepClone(); - String templateName; + String templateName = "_ast.builder.opt.Set4ASTBuilderOpt"; if (getDecorationHelper().isSupplier(type)) { - templateName = "_ast.builder.opt.SupplierSet4ASTBuilderOpt"; type = getDecorationHelper().unwrapSupplier(type); - } else { - templateName = "_ast.builder.opt.Set4ASTBuilderOpt"; + templateName = "_ast.builder.opt.SupplierSet4ASTBuilderOpt"; } ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); @@ -68,9 +66,10 @@ protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute attribute) { ASTMCReturnType returnType = MCBasicTypesMill.mCReturnTypeBuilder().setMCType(builderType).build(); method.setMCReturnType(returnType); - String templateName = getDecorationHelper().isSupplier(attribute.getMCType()) - ? "_ast.builder.opt.SupplierSetAbsent4ASTBuilderOpt" - : "_ast.builder.opt.SetAbsent4ASTBuilderOpt"; + String templateName = "_ast.builder.opt.SetAbsent4ASTBuilderOpt"; + if (getDecorationHelper().isSupplier(attribute.getMCType())) { + templateName = "_ast.builder.opt.SupplierSetAbsent4ASTBuilderOpt"; + } this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, attribute)); return method; diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java index 91d1869e8d..72bc90788e 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/inheritedmethods/InheritedBuilderOptionalMutatorDecorator.java @@ -28,7 +28,10 @@ public InheritedBuilderOptionalMutatorDecorator(final GlobalExtensionManagement @Override protected ASTCDMethod createSetMethod(final ASTCDAttribute attribute) { String name = String.format(SET, naiveAttributeName); - ASTMCType type = getDecorationHelper().unwrapSupplier(attribute.getMCType()); + ASTMCType type = attribute.getMCType().deepClone(); + if (getDecorationHelper().isSupplier(type)) { + type = getDecorationHelper().unwrapSupplier(type); + } ASTMCType parameterType = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); ASTCDParameter parameter = this.getCDParameterFacade().createParameter(parameterType, attribute.getName()); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name, parameter); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java index 1c9fddeb29..6e3ad3f6a0 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/ListAccessorDecorator.java @@ -55,11 +55,9 @@ protected ASTCDMethod createGetListMethod(ASTCDAttribute ast) { String signature = String.format(GET_LIST, attributeType, capitalizedAttributeNameWithOutS); ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature); - String templateName; + String templateName = "methods.Get"; if (getDecorationHelper().isSupplier(ast.getMCType())) { templateName = "methods.SupplierGet"; - } else { - templateName = "methods.Get"; } this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint(templateName, ast)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java index 53c555a840..98cee06bbc 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/MandatoryAccessorDecorator.java @@ -46,13 +46,11 @@ protected ASTCDMethod createGetter(final ASTCDAttribute ast) { String name = String.format(getterPrefix, StringUtils.capitalize(getDecorationHelper().getNativeAttributeName(ast.getName()))); ASTMCType type = ast.getMCType().deepClone(); - String templateName; + String templateName = "methods.Get"; if (getDecorationHelper().isSupplier(type)) { // The Supplier is hidden from the user. The getter has to expose the unwrapped type (Supplier -> X) type = getDecorationHelper().unwrapSupplier(type); templateName = "methods.SupplierGet"; - } else { - templateName = "methods.Get"; } ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), type, name); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java index 8c967ceead..18e2f5d1fc 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/accessor/OptionalAccessorDecorator.java @@ -52,12 +52,10 @@ protected ASTCDMethod createGetMethod(final ASTCDAttribute ast) { String name = String.format(GET, naiveAttributeName); ASTMCType type = ast.getMCType().deepClone(); - String templateName; - if (getDecorationHelper().isSupplier(type)){ - templateName = "methods.opt.SupplierGet4Opt"; + String templateName = "methods.opt.Get4Opt"; + if (getDecorationHelper().isSupplier(type)) { type = getDecorationHelper().unwrapSupplier(type); - } else { - templateName = "methods.opt.Get4Opt"; + templateName = "methods.opt.SupplierGet4Opt"; } type = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get(); @@ -79,11 +77,9 @@ protected ASTCDMethod createIsPresentMethod(final ASTCDAttribute ast) { String name = String.format(IS_PRESENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), getMCTypeFacade().createBooleanType(), name); - String templateName; - if (getDecorationHelper().isSupplier(ast.getMCType())){ + String templateName = "methods.opt.IsPresent4Opt"; + if (getDecorationHelper().isSupplier(ast.getMCType())) { templateName = "methods.opt.SupplierIsPresent4Opt"; - } else { - templateName = "methods.opt.IsPresent4Opt"; } this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java index 69441b9ed8..840048a2ce 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/ListMutatorDecorator.java @@ -51,11 +51,9 @@ protected ASTCDMethod createSetListMethod(ASTCDAttribute ast) { String signature = String.format(SET_LIST, capitalizedAttributeNameWithOutS, attributeType, ast.getName()); ASTCDMethod getList = this.getCDMethodFacade().createMethodByDefinition(signature); - String templateName; + String templateName = "methods.Set"; if (getDecorationHelper().isSupplier(ast.getMCType())) { templateName = "methods.SupplierSet"; - } else { - templateName = "methods.Set"; } this.replaceTemplate(EMPTY_BODY, getList, new TemplateHookPoint(templateName, ast)); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java index 6d56912897..12fa4d6d74 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/mutator/OptionalMutatorDecorator.java @@ -44,12 +44,10 @@ protected ASTCDMethod createSetMethod(final ASTCDAttribute ast) { String name = String.format(SET, naiveAttributeName); ASTMCType type = ast.getMCType().deepClone(); - String templateName; - if (getDecorationHelper().isSupplier(type)){ - templateName = "methods.opt.SupplierSet4Opt"; + String templateName = "methods.opt.Set4Opt"; + if (getDecorationHelper().isSupplier(type)) { type = getDecorationHelper().unwrapSupplier(type); - } else { - templateName = "methods.opt.Set4Opt"; + templateName = "methods.opt.SupplierSet4Opt"; } type = getDecorationHelper().getReferenceTypeOfOptional(type).getMCTypeOpt().get().deepClone(); @@ -72,11 +70,9 @@ protected ASTCDMethod createSetAbsentMethod(final ASTCDAttribute ast) { String name = String.format(SET_ABSENT, naiveAttributeName); ASTCDMethod method = this.getCDMethodFacade().createMethod(PUBLIC.build(), name); - String templateName; - if (getDecorationHelper().isSupplier(ast.getMCType())){ + String templateName = "methods.opt.SetAbsent"; + if (getDecorationHelper().isSupplier(ast.getMCType())) { templateName = "methods.opt.SupplierSetAbsent"; - } else { - templateName = "methods.opt.SetAbsent"; } this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(templateName, ast)); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java index f51ddc48d2..39e99d5560 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/FunctionSymbol.java @@ -23,7 +23,7 @@ public FunctionSymbol(String name){ public FunctionSymbol deepClone(){ FunctionSymbol clone = new FunctionSymbol(name); // keep the type lazy - clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), t -> t == null ? null : t.deepClone())); clone.setIsElliptic(this.isIsElliptic()); clone.setEnclosingScope(this.enclosingScope); clone.setFullName(this.fullName); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java index ab02cd9941..93c8d95ed7 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/basicsymbols/_symboltable/VariableSymbol.java @@ -24,7 +24,7 @@ public VariableSymbol deepClone(){ clone.setAstNode(this.getAstNode()); } // keep the type lazy - clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), t -> t == null ? null : t.deepClone())); return clone; } diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java index 8c39fc311b..7634be402a 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/FieldSymbol.java @@ -37,7 +37,7 @@ public FieldSymbol deepClone(){ clone.setAstNode(this.getAstNode()); } // keep the type lazy - clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), t -> t == null ? null : t.deepClone())); return clone; } diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java index 1d426e84a4..a0946773ae 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/oosymbols/_symboltable/MethodSymbol.java @@ -21,7 +21,7 @@ public MethodSymbol(String name) { public MethodSymbol deepClone() { MethodSymbol clone = new MethodSymbol(name); // keep the type lazy - clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), SymTypeExpression::deepClone)); + clone.setTypeSupplier(ClearingMemorizer.map(getTypeSupplier(), t -> t == null ? null : t.deepClone())); clone.setEnclosingScope(this.enclosingScope); clone.setFullName(this.fullName); clone.setIsConstructor(this.isConstructor); diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java b/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java index 66468c90d1..bb53057a86 100644 --- a/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/ClearingMemorizer.java @@ -20,14 +20,11 @@ public ClearingMemorizer(Supplier supplier) { /** * Lazily applies the mapper to the value of the source, evaluated at most once. - * A null value of the source stays null. Nothing is evaluated until the result is requested, - * e.g. to copy a not-yet-resolvable attribute of a symbol without forcing it. + * Nothing is evaluated until the result is requested, e.g. to copy a not-yet-resolvable + * attribute of a symbol without forcing it. */ public static Supplier map(Supplier source, Function mapper) { - return new ClearingMemorizer<>(() -> { - T value = source.get(); - return value == null ? null : mapper.apply(value); - }); + return new ClearingMemorizer<>(() -> mapper.apply(source.get())); } @Override From 0993d9478836f8b7a68f193ee2531e48a46e8fe3 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Tue, 22 Sep 2026 14:41:31 +0200 Subject: [PATCH 18/21] tests for new decorations --- .../scope/ScopeClassDecoratorTest.java | 158 +++++++++++++++++- .../symbol/SymbolBuilderDecoratorTest.java | 145 +++++++++++++++- .../symbol/SymbolDecoratorTest.java | 144 +++++++++++++++- .../codegen/symboltable/AutomatonScopeCD.cd | 3 + .../codegen/symboltable/AutomatonSymbolCD.cd | 3 + .../cdForBuilder/Symbol_Builder.cd | 4 +- 6 files changed, 446 insertions(+), 11 deletions(-) diff --git a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java index 65751a1315..c8431bc5aa 100644 --- a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java +++ b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java @@ -13,12 +13,15 @@ import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; import de.monticore.codegen.cd2java.AbstractService; +import de.monticore.codegen.cd2java.DecorationHelper; import de.monticore.codegen.cd2java.DecoratorTestCase; import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.GeneratorEngine; import de.monticore.generating.GeneratorSetup; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,6 +38,7 @@ import static de.monticore.codegen.cd2java.DecoratorAssert.assertOptionalOf; import static de.monticore.codegen.cd2java.DecoratorAssert.assertVoid; import static de.monticore.codegen.cd2java.DecoratorTestUtil.getAttributeBy; +import static de.monticore.codegen.cd2java.DecoratorTestUtil.getClassBy; import static de.monticore.codegen.cd2java.DecoratorTestUtil.getMethodBy; import static de.monticore.codegen.cd2java.DecoratorTestUtil.getMethodsBy; import static org.junit.jupiter.api.Assertions.*; @@ -43,8 +47,12 @@ public class ScopeClassDecoratorTest extends DecoratorTestCase { private ASTCDClass scopeClass; + private ASTCDClass originalScopeRuleClass; + private de.monticore.types.MCTypeFacade mcTypeFacade; + private static final String SYM_TYPE_EXPRESSION = "de.monticore.types.check.SymTypeExpression"; + private ASTCDCompilationUnit decoratedSymbolCompilationUnit; private ASTCDCompilationUnit decoratedScopeCompilationUnit; @@ -87,6 +95,7 @@ public void setUp() { ASTCDCompilationUnit astcdCompilationUnit = this.parse("de", "monticore", "codegen", "symboltable", "Automaton"); decoratedSymbolCompilationUnit = this.parse("de", "monticore", "codegen", "symboltable", "AutomatonSymbolCD"); decoratedScopeCompilationUnit = this.parse("de", "monticore", "codegen", "symboltable", "AutomatonScopeCD"); + originalScopeRuleClass = getClassBy("AutomatonScope", decoratedScopeCompilationUnit); originalCompilationUnit = decoratedSymbolCompilationUnit.deepClone(); this.glex.setGlobalValue("service", new AbstractService(astcdCompilationUnit)); @@ -208,7 +217,7 @@ public void testShadowingAndEnclosingScopeConstructor() { @Test public void testAttributeCount() { - assertEquals(21, scopeClass.getCDAttributeList().size()); + assertEquals(24, scopeClass.getCDAttributeList().size()); } @Test @@ -361,22 +370,163 @@ public void testScopeRuleAttributes() { ASTCDAttribute fooAttribute = getAttributeBy("foo", scopeClass); assertDeepEquals(PROTECTED, fooAttribute.getModifier()); assertListOf(String.class, fooAttribute.getMCType()); + assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(fooAttribute)); ASTCDAttribute blaAttribute = getAttributeBy("bla", scopeClass); assertDeepEquals(PROTECTED, blaAttribute.getModifier()); assertOptionalOf(Integer.class, blaAttribute.getMCType()); + assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(blaAttribute)); ASTCDAttribute extraAtt = getAttributeBy("extraAttribute", scopeClass); assertDeepEquals(PROTECTED, extraAtt.getModifier()); assertBoolean(extraAtt.getMCType()); - + assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(extraAtt)); + + // symType, lSymType and oSymType are of the types listed in AccessAsSupplierTypes, so arewrapped int + // internal Supplier type. + ASTCDAttribute originalSymTypeAttribute = getAttributeBy("symType", originalScopeRuleClass); + assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalSymTypeAttribute)); + ASTCDAttribute symTypeAttribute = getAttributeBy("symType", scopeClass); + assertDeepEquals(PROTECTED, symTypeAttribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalSymTypeAttribute.getMCType()), + symTypeAttribute.getMCType()); + + ASTCDAttribute originalLSymTypeAttribute = getAttributeBy("lSymType", originalScopeRuleClass); + assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalLSymTypeAttribute)); + ASTCDAttribute lSymTypeAttribute = getAttributeBy("lSymType", scopeClass); + assertDeepEquals(PROTECTED, lSymTypeAttribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalLSymTypeAttribute.getMCType()), + lSymTypeAttribute.getMCType()); + + ASTCDAttribute originalOSymTypeAttribute = getAttributeBy("oSymType", originalScopeRuleClass); + assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalOSymTypeAttribute)); + ASTCDAttribute oSymTypeAttribute = getAttributeBy("oSymType", scopeClass); + assertDeepEquals(PROTECTED, oSymTypeAttribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalOSymTypeAttribute.getMCType()), + oSymTypeAttribute.getMCType()); + + assertTrue(Log.getFindings().isEmpty()); + } + + + // getters/setters that have to be Supplier-wrapped (see AccessAsSupplierTypes) + // get additional fields, allowing to both set/get the Supplier itself and to set/get the value directly + + @Test + public void testSymTypeScopeRuleMethods() { + ASTMCType symTypeType = getAttributeBy("symType", originalScopeRuleClass).getMCType(); + + ASTCDMethod getter = getMethodBy("getSymType", scopeClass); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertDeepEquals(symTypeType, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setSymType", scopeClass); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertTrue(setter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, setter.sizeCDParameters()); + assertDeepEquals(symTypeType, setter.getCDParameter(0).getMCType()); + assertEquals("symType", setter.getCDParameter(0).getName()); + + ASTCDMethod supplierGetter = getMethodBy("getSymTypeSupplier", scopeClass); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setSymTypeSupplier", scopeClass); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertTrue(supplierSetter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("symType", supplierSetter.getCDParameter(0).getName()); + + assertTrue(Log.getFindings().isEmpty()); + } + + @Test + public void testLSymTypeScopeRuleMethods() { + ASTMCType lSymTypeType = getAttributeBy("lSymType", originalScopeRuleClass).getMCType(); + + ASTCDMethod getter = getMethodBy("getLSymTypeList", scopeClass); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertListOf(SYM_TYPE_EXPRESSION, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setLSymTypeList", scopeClass); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertTrue(setter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, setter.sizeCDParameters()); + assertListOf(SYM_TYPE_EXPRESSION, setter.getCDParameter(0).getMCType()); + assertEquals("lSymType", setter.getCDParameter(0).getName()); + + ASTCDMethod supplierGetter = getMethodBy("getLSymTypeListSupplier", scopeClass); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setLSymTypeListSupplier", scopeClass); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertTrue(supplierSetter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("lSymType", supplierSetter.getCDParameter(0).getName()); + + assertTrue(Log.getFindings().isEmpty()); + } + + @Test + public void testOSymTypeScopeRuleMethods() { + ASTCDAttribute originalOSymTypeAttribute = getAttributeBy("oSymType", originalScopeRuleClass); + ASTMCType oSymTypeType = originalOSymTypeAttribute.getMCType(); + ASTMCType innerType = DecorationHelper.getInstance().getReferenceTypeOfOptional(oSymTypeType).getMCTypeOpt().get(); + + ASTCDMethod getter = getMethodBy("getOSymType", scopeClass); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertDeepEquals(innerType, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod isPresent = getMethodBy("isPresentOSymType", scopeClass); + assertDeepEquals(PUBLIC, isPresent.getModifier()); + assertBoolean(isPresent.getMCReturnType().getMCType()); + assertTrue(isPresent.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setOSymType", scopeClass); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertTrue(setter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, setter.sizeCDParameters()); + assertDeepEquals(innerType, setter.getCDParameter(0).getMCType()); + assertEquals("oSymType", setter.getCDParameter(0).getName()); + + ASTCDMethod setAbsent = getMethodBy("setOSymTypeAbsent", scopeClass); + assertDeepEquals(PUBLIC, setAbsent.getModifier()); + assertTrue(setAbsent.getMCReturnType().isPresentMCVoidType()); + assertTrue(setAbsent.isEmptyCDParameters()); + + ASTCDMethod supplierGetter = getMethodBy("getOSymTypeSupplier", scopeClass); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setOSymTypeSupplier", scopeClass); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertTrue(supplierSetter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("oSymType", supplierSetter.getCDParameter(0).getName()); + assertTrue(Log.getFindings().isEmpty()); } @Test public void testMethodCount() { - assertEquals(104, scopeClass.getCDMethodList().size()); - + // previously here: =104 + // added because of supplied fields + // symType (mandatory): get+getSupplier, set+setSupplier = 4 + // lSymType (list): 18 delegate + getList + getListSupplier = 20 + // 14 delegate + setList + setListSupplier = 16 + // oSymType (optional): get+isPresent+getSupplier, set+setAbsent+setSupplier = 6 + assertEquals(104 + 4 + 20 + 16 + 6, scopeClass.getCDMethodList().size()); + assertTrue(Log.getFindings().isEmpty()); } diff --git a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java index 650a4a5302..2ea12e5991 100644 --- a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java +++ b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java @@ -13,6 +13,7 @@ import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; import de.monticore.codegen.cd2java.AbstractService; +import de.monticore.codegen.cd2java.DecorationHelper; import de.monticore.codegen.cd2java.DecoratorTestCase; import de.monticore.codegen.cd2java._ast.builder.BuilderDecorator; import de.monticore.codegen.cd2java._symboltable.SymbolTableService; @@ -20,6 +21,7 @@ import de.monticore.generating.GeneratorEngine; import de.monticore.generating.GeneratorSetup; import de.monticore.types.MCTypeFacade; +import de.monticore.types.mcbasictypes._ast.ASTMCType; import de.se_rwth.commons.logging.Log; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,6 +29,7 @@ import static de.monticore.cd.facade.CDModifier.PUBLIC; import static de.monticore.codegen.cd2java.DecoratorAssert.assertBoolean; import static de.monticore.codegen.cd2java.DecoratorAssert.assertDeepEquals; +import static de.monticore.codegen.cd2java.DecoratorAssert.assertListOf; import static de.monticore.codegen.cd2java.DecoratorTestUtil.getAttributeBy; import static de.monticore.codegen.cd2java.DecoratorTestUtil.getClassBy; import static de.monticore.codegen.cd2java.DecoratorTestUtil.getMethodBy; @@ -34,10 +37,14 @@ public class SymbolBuilderDecoratorTest extends DecoratorTestCase { + private ASTCDClass cdClass; + private ASTCDClass builderClass; private MCTypeFacade mcTypeFacade; + private static final String SYM_TYPE_EXPRESSION = "de.monticore.types.check.SymTypeExpression"; + private static final String ENCLOSING_SCOPE_TYPE = "de.monticore.codegen.symboltable.cdforbuilder.symbol_builder._symboltable.ISymbol_BuilderScope"; private static final String A_NODE_TYPE_OPT = "Optional"; @@ -55,7 +62,7 @@ public void setup() { this.mcTypeFacade = MCTypeFacade.getInstance(); ASTCDCompilationUnit ast = parse("de", "monticore", "codegen", "symboltable","cdForBuilder", "Symbol_Builder"); - ASTCDClass cdClass = getClassBy("A", ast); + cdClass = getClassBy("A", ast); this.glex.setGlobalValue("service", new AbstractService(ast)); AccessorDecorator methodDecorator = new AccessorDecorator(glex, new SymbolTableService(ast)); @@ -106,8 +113,130 @@ public void testDefaultConstructor() { @Test public void testAttributes() { - assertEquals(8, builderClass.getCDAttributeList().size()); - + assertEquals(11, builderClass.getCDAttributeList().size()); + + assertTrue(Log.getFindings().isEmpty()); + } + + // getters/setters that have to be Supplier-wrapped (see AccessAsSupplierTypes) + // get additional fields. allowing to both set/get the Supplier itself and to set/get the value directly + + @Test + public void testSymTypeAttributeAndMethods() { + ASTCDAttribute originalAttribute = getAttributeBy("symType", cdClass); + ASTMCType symTypeType = originalAttribute.getMCType(); + + ASTCDAttribute attribute = getAttributeBy("symType", builderClass); + assertDeepEquals(CDModifier.PROTECTED, attribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(symTypeType), attribute.getMCType()); + + ASTCDMethod getter = getMethodBy("getSymType", builderClass); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertDeepEquals(symTypeType, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setSymType", builderClass); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertDeepEquals(builderClass.getName(), setter.getMCReturnType().getMCType()); + assertEquals(1, setter.sizeCDParameters()); + assertDeepEquals(symTypeType, setter.getCDParameter(0).getMCType()); + assertEquals("symType", setter.getCDParameter(0).getName()); + + ASTCDMethod supplierGetter = getMethodBy("getSymTypeSupplier", builderClass); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setSymTypeSupplier", builderClass); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertDeepEquals(builderClass.getName(), supplierSetter.getMCReturnType().getMCType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("symType", supplierSetter.getCDParameter(0).getName()); + + assertTrue(Log.getFindings().isEmpty()); + } + + @Test + public void testLSymTypeAttributeAndMethods() { + ASTCDAttribute originalAttribute = getAttributeBy("lSymType", cdClass); + ASTMCType lSymTypeType = originalAttribute.getMCType(); + + ASTCDAttribute attribute = getAttributeBy("lSymType", builderClass); + assertDeepEquals(CDModifier.PROTECTED, attribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(lSymTypeType), attribute.getMCType()); + + ASTCDMethod getter = getMethodBy("getLSymTypeList", builderClass); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertListOf(SYM_TYPE_EXPRESSION, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setLSymTypeList", builderClass); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertDeepEquals(builderClass.getName(), setter.getMCReturnType().getMCType()); + assertEquals(1, setter.sizeCDParameters()); + assertListOf(SYM_TYPE_EXPRESSION, setter.getCDParameter(0).getMCType()); + assertEquals("lSymType", setter.getCDParameter(0).getName()); + + ASTCDMethod supplierGetter = getMethodBy("getLSymTypeListSupplier", builderClass); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setLSymTypeListSupplier", builderClass); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertDeepEquals(builderClass.getName(), supplierSetter.getMCReturnType().getMCType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("lSymType", supplierSetter.getCDParameter(0).getName()); + + assertTrue(Log.getFindings().isEmpty()); + } + + @Test + public void testOSymTypeAttributeAndMethods() { + ASTCDAttribute originalAttribute = getAttributeBy("oSymType", cdClass); + ASTMCType oSymTypeType = originalAttribute.getMCType(); + ASTMCType innerType = DecorationHelper.getInstance().getReferenceTypeOfOptional(oSymTypeType).getMCTypeOpt().get(); + + ASTCDAttribute attribute = getAttributeBy("oSymType", builderClass); + assertDeepEquals(CDModifier.PROTECTED, attribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(oSymTypeType), attribute.getMCType()); + + ASTCDMethod getter = getMethodBy("getOSymType", builderClass); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertDeepEquals(innerType, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod isPresent = getMethodBy("isPresentOSymType", builderClass); + assertDeepEquals(PUBLIC, isPresent.getModifier()); + assertBoolean(isPresent.getMCReturnType().getMCType()); + assertTrue(isPresent.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setOSymType", builderClass); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertDeepEquals(builderClass.getName(), setter.getMCReturnType().getMCType()); + assertEquals(1, setter.sizeCDParameters()); + assertDeepEquals(innerType, setter.getCDParameter(0).getMCType()); + assertEquals("oSymType", setter.getCDParameter(0).getName()); + + ASTCDMethod setAbsent = getMethodBy("setOSymTypeAbsent", builderClass); + assertDeepEquals(PUBLIC, setAbsent.getModifier()); + assertDeepEquals(builderClass.getName(), setAbsent.getMCReturnType().getMCType()); + assertTrue(setAbsent.isEmptyCDParameters()); + + ASTCDMethod supplierGetter = getMethodBy("getOSymTypeSupplier", builderClass); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setOSymTypeSupplier", builderClass); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertDeepEquals(builderClass.getName(), supplierSetter.getMCReturnType().getMCType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("oSymType", supplierSetter.getCDParameter(0).getName()); + assertTrue(Log.getFindings().isEmpty()); } @@ -185,8 +314,14 @@ public void testStereoinfoAttribute() { @Test public void testMethods() { - assertEquals(20, builderClass.getCDMethodList().size()); - + // previously here: 20 + // added because of supplied fields + // symType (mandatory): get+getSupplier, set+setSupplier = 4 + // lSymType (list): 18 delegate + getList + getListSupplier = 20 + // 14 delegate + setList + setListSupplier = 16 + // oSymType (optional): get+isPresent+getSupplier, set+setAbsent+setSupplier = 6 + assertEquals(20 + 4 + 20 + 16 + 6, builderClass.getCDMethodList().size()); + assertTrue(Log.getFindings().isEmpty()); } diff --git a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java index 92e55b08f2..a1dfdbe523 100644 --- a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java +++ b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java @@ -13,9 +13,11 @@ import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; import de.monticore.codegen.cd2java.AbstractService; +import de.monticore.codegen.cd2java.DecorationHelper; import de.monticore.codegen.cd2java.DecoratorTestCase; import de.monticore.codegen.cd2java._symboltable.SymbolTableService; import de.monticore.codegen.cd2java._visitor.VisitorService; +import de.monticore.codegen.cd2java.methods.AccessAsSupplierTypes; import de.monticore.codegen.cd2java.methods.MethodDecorator; import de.monticore.generating.GeneratorEngine; import de.monticore.generating.GeneratorSetup; @@ -55,6 +57,10 @@ public class SymbolDecoratorTest extends DecoratorTestCase { private ASTCDCompilationUnit originalCompilationUnit; + private ASTCDClass originalFooClass; + + private static final String SYM_TYPE_EXPRESSION = "de.monticore.types.check.SymTypeExpression"; + private static final String ENCLOSING_SCOPE_TYPE = "de.monticore.codegen.symboltable.automatonsymbolcd._symboltable.IAutomatonSymbolCDScope"; private static final String A_NODE_TYPE_OPT = "Optional"; @@ -77,6 +83,7 @@ public void setUp() { decoratedCompilationUnit = this.parse("de", "monticore", "codegen", "symboltable", "AutomatonSymbolCD"); originalCompilationUnit = decoratedCompilationUnit.deepClone(); + originalFooClass = getClassBy("Foo", originalCompilationUnit); this.glex.setGlobalValue("service", new AbstractService(decoratedCompilationUnit)); @@ -247,15 +254,150 @@ public void testSymbolRuleAttributes() { ASTCDAttribute fooAttribute = getAttributeBy("foo", symbolClassFoo); assertDeepEquals(PROTECTED, fooAttribute.getModifier()); assertListOf(String.class, fooAttribute.getMCType()); + assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(fooAttribute)); ASTCDAttribute blaAttribute = getAttributeBy("bla", symbolClassFoo); assertDeepEquals(PROTECTED, blaAttribute.getModifier()); assertOptionalOf(Integer.class, blaAttribute.getMCType()); + assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(blaAttribute)); ASTCDAttribute extraAtt = getAttributeBy("extraAttribute", symbolClassFoo); assertDeepEquals(PROTECTED, extraAtt.getModifier()); assertBoolean(extraAtt.getMCType()); - + assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(extraAtt)); + + // symType, lSymType and oSymType are of the types listed in AccessAsSupplierTypes, so the + // decorator must wrap their attribute type into the internal Supplier type. + ASTCDAttribute originalSymTypeAttribute = getAttributeBy("symType", originalFooClass); + assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalSymTypeAttribute)); + ASTCDAttribute symTypeAttribute = getAttributeBy("symType", symbolClassFoo); + assertDeepEquals(PROTECTED, symTypeAttribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalSymTypeAttribute.getMCType()), + symTypeAttribute.getMCType()); + + ASTCDAttribute originalLSymTypeAttribute = getAttributeBy("lSymType", originalFooClass); + assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalLSymTypeAttribute)); + ASTCDAttribute lSymTypeAttribute = getAttributeBy("lSymType", symbolClassFoo); + assertDeepEquals(PROTECTED, lSymTypeAttribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalLSymTypeAttribute.getMCType()), + lSymTypeAttribute.getMCType()); + + ASTCDAttribute originalOSymTypeAttribute = getAttributeBy("oSymType", originalFooClass); + assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalOSymTypeAttribute)); + ASTCDAttribute oSymTypeAttribute = getAttributeBy("oSymType", symbolClassFoo); + assertDeepEquals(PROTECTED, oSymTypeAttribute.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalOSymTypeAttribute.getMCType()), + oSymTypeAttribute.getMCType()); + + assertTrue(Log.getFindings().isEmpty()); + } + + // getters/setters for the Supplier-wrapped symbolrule attributes (see AccessAsSupplierTypes): + // each of them gets a plain getter/setter that hides the Supplier (exposing the unwrapped type), + // plus an additional "...Supplier" getter/setter that exposes the java.util.function.Supplier itself. + + @Test + public void testSymTypeSymbolRuleMethods() { + ASTMCType symTypeType = getAttributeBy("symType", originalFooClass).getMCType(); + + ASTCDMethod getter = getMethodBy("getSymType", symbolClassFoo); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertDeepEquals(symTypeType, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setSymType", symbolClassFoo); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertTrue(setter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, setter.sizeCDParameters()); + assertDeepEquals(symTypeType, setter.getCDParameter(0).getMCType()); + assertEquals("symType", setter.getCDParameter(0).getName()); + + ASTCDMethod supplierGetter = getMethodBy("getSymTypeSupplier", symbolClassFoo); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setSymTypeSupplier", symbolClassFoo); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertTrue(supplierSetter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("symType", supplierSetter.getCDParameter(0).getName()); + + assertTrue(Log.getFindings().isEmpty()); + } + + @Test + public void testListSymTypeSymbolRuleMethods() { + ASTMCType lSymTypeType = getAttributeBy("lSymType", originalFooClass).getMCType(); + + ASTCDMethod getter = getMethodBy("getLSymTypeList", symbolClassFoo); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertListOf(SYM_TYPE_EXPRESSION, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setLSymTypeList", symbolClassFoo); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertTrue(setter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, setter.sizeCDParameters()); + assertListOf(SYM_TYPE_EXPRESSION, setter.getCDParameter(0).getMCType()); + assertEquals("lSymType", setter.getCDParameter(0).getName()); + + ASTCDMethod supplierGetter = getMethodBy("getLSymTypeListSupplier", symbolClassFoo); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setLSymTypeListSupplier", symbolClassFoo); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertTrue(supplierSetter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("lSymType", supplierSetter.getCDParameter(0).getName()); + + assertTrue(Log.getFindings().isEmpty()); + } + + @Test + public void testOptionalSymTypeSymbolRuleMethods() { + ASTCDAttribute originalOSymTypeAttribute = getAttributeBy("oSymType", originalFooClass); + ASTMCType oSymTypeType = originalOSymTypeAttribute.getMCType(); + ASTMCType innerType = DecorationHelper.getInstance().getReferenceTypeOfOptional(oSymTypeType).getMCTypeOpt().get(); + + ASTCDMethod getter = getMethodBy("getOSymType", symbolClassFoo); + assertDeepEquals(PUBLIC, getter.getModifier()); + assertDeepEquals(innerType, getter.getMCReturnType().getMCType()); + assertTrue(getter.isEmptyCDParameters()); + + ASTCDMethod isPresent = getMethodBy("isPresentOSymType", symbolClassFoo); + assertDeepEquals(PUBLIC, isPresent.getModifier()); + assertBoolean(isPresent.getMCReturnType().getMCType()); + assertTrue(isPresent.isEmptyCDParameters()); + + ASTCDMethod setter = getMethodBy("setOSymType", symbolClassFoo); + assertDeepEquals(PUBLIC, setter.getModifier()); + assertTrue(setter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, setter.sizeCDParameters()); + assertDeepEquals(innerType, setter.getCDParameter(0).getMCType()); + assertEquals("oSymType", setter.getCDParameter(0).getName()); + + ASTCDMethod setAbsent = getMethodBy("setOSymTypeAbsent", symbolClassFoo); + assertDeepEquals(PUBLIC, setAbsent.getModifier()); + assertTrue(setAbsent.getMCReturnType().isPresentMCVoidType()); + assertTrue(setAbsent.isEmptyCDParameters()); + + ASTCDMethod supplierGetter = getMethodBy("getOSymTypeSupplier", symbolClassFoo); + assertDeepEquals(PUBLIC, supplierGetter.getModifier()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), supplierGetter.getMCReturnType().getMCType()); + assertTrue(supplierGetter.isEmptyCDParameters()); + + ASTCDMethod supplierSetter = getMethodBy("setOSymTypeSupplier", symbolClassFoo); + assertDeepEquals(PUBLIC, supplierSetter.getModifier()); + assertTrue(supplierSetter.getMCReturnType().isPresentMCVoidType()); + assertEquals(1, supplierSetter.sizeCDParameters()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), supplierSetter.getCDParameter(0).getMCType()); + assertEquals("oSymType", supplierSetter.getCDParameter(0).getName()); + assertTrue(Log.getFindings().isEmpty()); } diff --git a/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonScopeCD.cd b/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonScopeCD.cd index a7f2f4988e..7d1255519b 100644 --- a/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonScopeCD.cd +++ b/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonScopeCD.cd @@ -9,6 +9,9 @@ classdiagram AutomatonScopeCD { protected boolean extraAttribute; protected List foo; protected Optional bla; + protected de.monticore.types.check.SymTypeExpression symType; + protected java.util.List lSymType; + protected java.util.Optional oSymType; <>public String toString(); } } diff --git a/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonSymbolCD.cd b/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonSymbolCD.cd index 8f25f7c269..532ade0272 100644 --- a/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonSymbolCD.cd +++ b/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/AutomatonSymbolCD.cd @@ -16,6 +16,9 @@ classdiagram AutomatonSymbolCD { protected boolean extraAttribute; protected List foo; protected Optional bla; + protected de.monticore.types.check.SymTypeExpression symType; + protected java.util.List lSymType; + protected java.util.Optional oSymType; <>public String toString(); } } diff --git a/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/cdForBuilder/Symbol_Builder.cd b/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/cdForBuilder/Symbol_Builder.cd index 542056ee9d..ee97a9649f 100644 --- a/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/cdForBuilder/Symbol_Builder.cd +++ b/monticore-generator/src/test/resources/de/monticore/codegen/symboltable/cdForBuilder/Symbol_Builder.cd @@ -4,6 +4,8 @@ package de.monticore.codegen.symboltable.cdForBuilder; classdiagram Symbol_Builder { class A { - + protected de.monticore.types.check.SymTypeExpression symType; + protected java.util.List lSymType; + protected java.util.Optional oSymType; } } From 396e9b5f428e4f816fc16326f92d117ce9dca3a7 Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Wed, 23 Sep 2026 12:49:10 +0200 Subject: [PATCH 19/21] tests for new decorations --- .../SymTypeExpressionSerStrategy.java | 6 +- .../builder/SupplierSetRaw4ASTBuilder.ftl | 2 +- .../_symboltable/symbol/BuildSymbol.ftl | 3 +- .../main/resources/methods/SupplierGetRaw.ftl | 2 +- .../main/resources/methods/SupplierSetRaw.ftl | 2 +- .../monticore/suppliedtypes/SuppliedTypes.mc4 | 20 ++ .../suppliedtypes/SuppliedTypesTest.java | 258 ++++++++++++++++++ .../symboltable/__internal__Supplier.java | 17 +- 8 files changed, 293 insertions(+), 17 deletions(-) create mode 100644 monticore-grammar/src/test/grammars/de/monticore/suppliedtypes/SuppliedTypes.mc4 create mode 100644 monticore-grammar/src/test/java/de/monticore/suppliedtypes/SuppliedTypesTest.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java index 4930bbfd27..f850c0004d 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/serialization/SymTypeExpressionSerStrategy.java @@ -30,16 +30,16 @@ public HookPoint getListSerialHook(String attrParam) { @Override public HookPoint getDeserialHook(String jsonParam, String attrParam, String scopeName) { - return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer<>(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); + return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); } @Override public HookPoint getOptDeserialHook(String jsonParam, String attrParam, String scopeName) { - return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer<>(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeOptionalMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); + return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer>(() -> 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 new de.monticore.symboltable.ClearingMemorizer<>(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeListMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); + return new StringHookPoint(String.format("return new de.monticore.symboltable.ClearingMemorizer>(() -> de.monticore.types.check.SymTypeExpressionDeSer.deserializeListMember(\"%s\", %s, %s));", attrParam, jsonParam, scopeName)); } } diff --git a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl index 0ce770786f..ea6e5d352c 100644 --- a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl +++ b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl @@ -1,6 +1,6 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = de.monticore.symboltable.__internal__Supplier.of(${attribute.getName()}); +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); ${defineHookPoint("Setter:After")} return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl b/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl index ed0fc2e9de..a58f3cfff6 100644 --- a/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl +++ b/monticore-generator/src/main/resources/_symboltable/symbol/BuildSymbol.ftl @@ -5,7 +5,8 @@ ${symbolClassName} symbol = new ${symbolClassName}(name); <#list attributes as attribute> <#assign setter = genHelper.getPlainSetter(attribute)> <#if genHelper.isSupplier(attribute.getMCType())> - symbol.${setter}Supplier(this.${attribute.getName()}); + <#assign getter = genHelper.getPlainGetter(attribute)> + symbol.${setter}Supplier(this.${getter}Supplier()); <#elseif genHelper.isOptional(attribute.getMCType())> if (this.${attribute.getName()}.isPresent()) { symbol.${setter}(this.${attribute.getName()}.get()); diff --git a/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl index 1f1de2a52a..9a6b96b9fd 100644 --- a/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl @@ -1,3 +1,3 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -return this.${attribute.getName()}; +return this.${attribute.getName()}.unwrap(); diff --git a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl index 947870a83a..5143bf4b97 100644 --- a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = de.monticore.symboltable.__internal__Supplier.of(${attribute.getName()}); +this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); ${defineHookPoint("Setter:After")} diff --git a/monticore-grammar/src/test/grammars/de/monticore/suppliedtypes/SuppliedTypes.mc4 b/monticore-grammar/src/test/grammars/de/monticore/suppliedtypes/SuppliedTypes.mc4 new file mode 100644 index 0000000000..172e56d6c5 --- /dev/null +++ b/monticore-grammar/src/test/grammars/de/monticore/suppliedtypes/SuppliedTypes.mc4 @@ -0,0 +1,20 @@ +/* (c) https://github.com/MontiCore/monticore */ + +package de.monticore.suppliedtypes; + + +grammar SuppliedTypes extends de.monticore.symbols.BasicSymbols { + + symbol Holder = "holder" Name; + + symbolrule Holder = + mandatoryType: de.monticore.types.check.SymTypeExpression + listType: de.monticore.types.check.SymTypeExpression* + optType: de.monticore.types.check.SymTypeExpression?; + + scoperule = + mandatoryType: de.monticore.types.check.SymTypeExpression + listType: de.monticore.types.check.SymTypeExpression* + optType: de.monticore.types.check.SymTypeExpression?; + +} diff --git a/monticore-grammar/src/test/java/de/monticore/suppliedtypes/SuppliedTypesTest.java b/monticore-grammar/src/test/java/de/monticore/suppliedtypes/SuppliedTypesTest.java new file mode 100644 index 0000000000..b54a801406 --- /dev/null +++ b/monticore-grammar/src/test/java/de/monticore/suppliedtypes/SuppliedTypesTest.java @@ -0,0 +1,258 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.suppliedtypes; + +import de.monticore.runtime.junit.TestWithMCLanguage; +import de.monticore.suppliedtypes.suppliedtypes.SuppliedTypesMill; +import de.monticore.suppliedtypes.suppliedtypes._symboltable.HolderSymbol; +import de.monticore.suppliedtypes.suppliedtypes._symboltable.HolderSymbolBuilder; +import de.monticore.suppliedtypes.suppliedtypes._symboltable.ISuppliedTypesScope; +import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.types.check.SymTypeExpression; +import de.monticore.types.check.SymTypeExpressionFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; + +import static org.junit.jupiter.api.Assertions.*; + +@TestWithMCLanguage(SuppliedTypesMill.class) +public class SuppliedTypesTest { + + private SymTypeExpression intType; + + private SymTypeExpression booleanType; + + @BeforeEach + public void init() { + BasicSymbolsMill.initializePrimitives(); + intType = SymTypeExpressionFactory.createPrimitive("int"); + booleanType = SymTypeExpressionFactory.createPrimitive("boolean"); + } + + @Test + public void symbolMandatoryType() { + HolderSymbol symbol = new HolderSymbol("holder"); + + // default: no value set yet + assertNull(symbol.getMandatoryType()); + + symbol.setMandatoryType(intType); + assertSame(intType, symbol.getMandatoryType()); + assertSame(intType, symbol.getMandatoryTypeSupplier().get()); + + symbol.setMandatoryTypeSupplier(() -> booleanType); + assertSame(booleanType, symbol.getMandatoryType()); + + // getXSupplier() must never leak the internal wrapper: it returns exactly what was set + Supplier plainSupplier = () -> intType; + symbol.setMandatoryTypeSupplier(plainSupplier); + assertSame(plainSupplier, symbol.getMandatoryTypeSupplier()); + } + + @Test + public void symbolListType() { + HolderSymbol symbol = new HolderSymbol("holder"); + + // default: an empty, non-null list + assertNotNull(symbol.getListTypeList()); + assertTrue(symbol.getListTypeList().isEmpty()); + + List values = List.of(intType, booleanType); + symbol.setListTypeList(values); + assertEquals(values, symbol.getListTypeList()); + assertEquals(values, symbol.getListTypeListSupplier().get()); + + symbol.setListTypeListSupplier(() -> values); + assertEquals(values, symbol.getListTypeList()); + + // getXSupplier() it returns exactly what was set + Supplier> plainSupplier = () -> values; + symbol.setListTypeListSupplier(plainSupplier); + assertSame(plainSupplier, symbol.getListTypeListSupplier()); + } + + @Test + public void symbolOptType() { + HolderSymbol symbol = new HolderSymbol("holder"); + + // default: absent + assertFalse(symbol.isPresentOptType()); + assertNull(symbol.getOptType()); + + symbol.setOptType(booleanType); + assertTrue(symbol.isPresentOptType()); + assertSame(booleanType, symbol.getOptType()); + assertEquals(java.util.Optional.of(booleanType), symbol.getOptTypeSupplier().get()); + + // removing value + symbol.setOptTypeAbsent(); + assertFalse(symbol.isPresentOptType()); + assertNull(symbol.getOptType()); + + + symbol.setOptTypeSupplier(() -> Optional.of(intType)); + assertTrue(symbol.isPresentOptType()); + assertSame(intType, symbol.getOptType()); + + // getXSupplier() it returns exactly what was set + Supplier> plainSupplier = () -> Optional.of(booleanType); + symbol.setOptTypeSupplier(plainSupplier); + assertSame(plainSupplier, symbol.getOptTypeSupplier()); + } + + @Test + public void scopeMandatoryType() { + ISuppliedTypesScope scope = SuppliedTypesMill.scope(); + + // default: no value set yet + assertNull(scope.getMandatoryType()); + + scope.setMandatoryType(intType); + assertSame(intType, scope.getMandatoryType()); + assertSame(intType, scope.getMandatoryTypeSupplier().get()); + + scope.setMandatoryTypeSupplier(() -> booleanType); + assertSame(booleanType, scope.getMandatoryType()); + + // getXSupplier() must never leak the internal wrapper: it returns exactly what was set + Supplier plainSupplier = () -> intType; + scope.setMandatoryTypeSupplier(plainSupplier); + assertSame(plainSupplier, scope.getMandatoryTypeSupplier()); + } + + @Test + public void scopeListType() { + ISuppliedTypesScope scope = SuppliedTypesMill.scope(); + + // default: an empty, non-null list + assertNotNull(scope.getListTypeList()); + assertTrue(scope.getListTypeList().isEmpty()); + + List values = List.of(intType, booleanType); + scope.setListTypeList(values); + assertEquals(values, scope.getListTypeList()); + assertEquals(values, scope.getListTypeListSupplier().get()); + + scope.setListTypeListSupplier(() -> values); + assertEquals(values, scope.getListTypeList()); + + // getXSupplier() it returns exactly what was set + Supplier> plainSupplier = () -> values; + scope.setListTypeListSupplier(plainSupplier); + assertSame(plainSupplier, scope.getListTypeListSupplier()); + } + + @Test + public void scopeOptType() { + ISuppliedTypesScope scope = SuppliedTypesMill.scope(); + + // default: absent + assertFalse(scope.isPresentOptType()); + assertNull(scope.getOptType()); + + scope.setOptType(booleanType); + assertTrue(scope.isPresentOptType()); + assertSame(booleanType, scope.getOptType()); + assertEquals(java.util.Optional.of(booleanType), scope.getOptTypeSupplier().get()); + + // removing value + scope.setOptTypeAbsent(); + assertFalse(scope.isPresentOptType()); + assertNull(scope.getOptType()); + + + scope.setOptTypeSupplier(() -> Optional.of(intType)); + assertTrue(scope.isPresentOptType()); + assertSame(intType, scope.getOptType()); + + // getXSupplier() it returns exactly what was set + Supplier> plainSupplier = () -> Optional.of(booleanType); + scope.setOptTypeSupplier(plainSupplier); + assertSame(plainSupplier, scope.getOptTypeSupplier()); + } + + @Test + public void builderMandatoryType() { + HolderSymbolBuilder builder = SuppliedTypesMill.holderSymbolBuilder(); + + // default: no value set yet + assertNull(builder.getMandatoryType()); + + builder.setMandatoryType(intType); + assertSame(intType, builder.getMandatoryType()); + assertSame(intType, builder.getMandatoryTypeSupplier().get()); + + builder.setMandatoryTypeSupplier(() -> booleanType); + assertSame(booleanType, builder.getMandatoryType()); + + // getXSupplier() it returns exactly what was set + Supplier plainSupplier = () -> intType; + builder.setMandatoryTypeSupplier(plainSupplier); + assertSame(plainSupplier, builder.getMandatoryTypeSupplier()); + } + + @Test + public void builderListType() { + HolderSymbolBuilder builder = SuppliedTypesMill.holderSymbolBuilder(); + + // default: an empty, non-null list + assertNotNull(builder.getListTypeList()); + assertTrue(builder.getListTypeList().isEmpty()); + + List values = List.of(intType, booleanType); + builder.setListTypeList(values); + assertEquals(values, builder.getListTypeList()); + assertEquals(values, builder.getListTypeListSupplier().get()); + + builder.setListTypeListSupplier(() -> values); + assertEquals(values, builder.getListTypeList()); + + // getXSupplier() it returns exactly what was set + Supplier> plainSupplier = () -> values; + builder.setListTypeListSupplier(plainSupplier); + assertSame(plainSupplier, builder.getListTypeListSupplier()); + } + + @Test + public void builderOptType() { + HolderSymbolBuilder builder = SuppliedTypesMill.holderSymbolBuilder(); + + // default: absent + assertFalse(builder.isPresentOptType()); + assertNull(builder.getOptType()); + + builder.setOptType(booleanType); + assertTrue(builder.isPresentOptType()); + assertSame(booleanType, builder.getOptType()); + assertEquals(Optional.of(booleanType), builder.getOptTypeSupplier().get()); + + // removing value + builder.setOptTypeAbsent(); + assertFalse(builder.isPresentOptType()); + assertNull(builder.getOptType()); + + builder.setOptTypeSupplier(() -> Optional.of(intType)); + assertTrue(builder.isPresentOptType()); + assertSame(intType, builder.getOptType()); + + // getXSupplier() it returns exactly what was set + Supplier> plainSupplier = () -> Optional.of(booleanType); + builder.setOptTypeSupplier(plainSupplier); + assertSame(plainSupplier, builder.getOptTypeSupplier()); + } + + @Test + public void builderDefaultsPropagateToTheBuiltSymbol() { + HolderSymbol symbol = SuppliedTypesMill.holderSymbolBuilder() + .setName("holder") + .build(); + + assertNull(symbol.getMandatoryType()); + assertNotNull(symbol.getListTypeList()); + assertTrue(symbol.getListTypeList().isEmpty()); + assertFalse(symbol.isPresentOptType()); + } +} diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java index eb0819cd35..a2c60cd5e8 100644 --- a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java +++ b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java @@ -17,18 +17,15 @@ public __internal__Supplier(Supplier supplier) { this.supplier = supplier; } - /** - * Wraps the supplier, unless it already is wrapped (avoids double-wrapping). - */ - public static __internal__Supplier of(Supplier supplier) { - if (supplier instanceof __internal__Supplier wrapped) { - return wrapped; - } - return new __internal__Supplier<>(supplier); - } - @Override public T get() { return supplier.get(); } + + /** + * Returns the supplier this instance wraps. + */ + public Supplier unwrap() { + return supplier; + } } From 8ac98c6abc3b2ab593f956da6249b88b8c98281b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=BCtticke?= Date: Thu, 1 Oct 2026 09:40:15 +0200 Subject: [PATCH 20/21] moved resolveOrLogError to out of factory --- .../types/check/SymTypeExpressionDeSer.java | 30 +++++++++++++++++++ .../types/check/SymTypeExpressionFactory.java | 29 ------------------ .../types/check/SymTypeOfGenericsDeSer.java | 2 +- .../types/check/SymTypeOfObjectDeSer.java | 2 +- .../types/check/SymTypeVariableDeSer.java | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionDeSer.java index 3c9fae774e..137eff16cc 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionDeSer.java @@ -3,6 +3,8 @@ import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.monticore.symbols.basicsymbols._symboltable.IBasicSymbolsScope; +import de.monticore.symbols.basicsymbols._symboltable.TypeSymbol; +import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; import de.monticore.symboltable.serialization.JsonDeSers; import de.monticore.symboltable.serialization.JsonParser; import de.monticore.symboltable.serialization.JsonPrinter; @@ -138,6 +140,34 @@ public static List deserializeListMember( return result; } + public static TypeSymbol resolveTypeSymbolOrLogError( + String name, IBasicSymbolsScope enclosingScope) { + Optional resolved = enclosingScope.resolveType(name); + if (resolved.isPresent()) { + return resolved.get(); + } + Log.error("0x893F63 Internal error: cannot resolve the type \"" + + name + "\" required by a SymTypeExpression!"); + TypeSymbol unresolved = new TypeSymbol(name); + unresolved.setEnclosingScope(enclosingScope); + unresolved.setFullName(name); + return unresolved; + } + + public static TypeVarSymbol resolveTypeVarSymbolOrLogError( + String name, IBasicSymbolsScope enclosingScope) { + Optional resolved = enclosingScope.resolveTypeVar(name); + if (resolved.isPresent()) { + return resolved.get(); + } + Log.error("0x893F64 Internal error: cannot resolve the type variable \"" + + name + "\" required by a SymTypeExpression!"); + TypeVarSymbol unresolved = new TypeVarSymbol(name); + unresolved.setEnclosingScope(enclosingScope); + unresolved.setFullName(name); + return unresolved; + } + public static SymTypeExpressionDeSer getInstance() { if (null == instance) { instance = new SymTypeExpressionDeSer(); diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java index 2ec4438534..f883f5cf2d 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeExpressionFactory.java @@ -162,35 +162,6 @@ public static SymTypeOfObject createTypeObjectViaSurrogate(String name, IBasicSy } - public static TypeSymbol resolveTypeSymbolOrLogError( - String name, IBasicSymbolsScope enclosingScope) { - Optional resolved = enclosingScope.resolveType(name); - if (resolved.isPresent()) { - return resolved.get(); - } - Log.error("0x893F63 Internal error: cannot resolve the type \"" - + name + "\" required by a SymTypeExpression!"); - TypeSymbol unresolved = new TypeSymbol(name); - unresolved.setEnclosingScope(enclosingScope); - unresolved.setFullName(name); - return unresolved; - } - - - public static TypeVarSymbol resolveTypeVarSymbolOrLogError( - String name, IBasicSymbolsScope enclosingScope) { - Optional resolved = enclosingScope.resolveTypeVar(name); - if (resolved.isPresent()) { - return resolved.get(); - } - Log.error("0x893F64 Internal error: cannot resolve the type variable \"" - + name + "\" required by a SymTypeExpression!"); - TypeVarSymbol unresolved = new TypeVarSymbol(name); - unresolved.setEnclosingScope(enclosingScope); - unresolved.setFullName(name); - return unresolved; - } - /** * for RegEx-types, e.g. 'R"gr(a|e)y"' */ diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java index 1fce3a3de4..07fd3072a8 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfGenericsDeSer.java @@ -50,7 +50,7 @@ public SymTypeOfGenerics deserialize(JsonObject serialized, IBasicSymbolsScope e List arguments = SymTypeExpressionDeSer .deserializeListMember(SERIALIZED_ARGUMENTS, serialized, enclosingScope); - return SymTypeExpressionFactory.createGenerics(SymTypeExpressionFactory + return SymTypeExpressionFactory.createGenerics(SymTypeExpressionDeSer .resolveTypeSymbolOrLogError(typeConstructorFullName, enclosingScope), arguments); } Log.error( diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java index a40a83125d..781b0a2b8e 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeOfObjectDeSer.java @@ -42,7 +42,7 @@ public SymTypeOfObject deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior enclosingScope = BasicSymbolsMill.globalScope(); } - return SymTypeExpressionFactory.createTypeObject(SymTypeExpressionFactory + return SymTypeExpressionFactory.createTypeObject(SymTypeExpressionDeSer .resolveTypeSymbolOrLogError(objName, enclosingScope)); } Log.error("0x823F4 Internal error: Cannot load \"" diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java index 647ebbd226..bbfb484aa2 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/SymTypeVariableDeSer.java @@ -50,7 +50,7 @@ public SymTypeVariable deserialize(JsonObject serialized, IBasicSymbolsScope enc // support deprecated behavior: enclosingScope = BasicSymbolsMill.globalScope(); } - return SymTypeExpressionFactory.createTypeVariable(SymTypeExpressionFactory + return SymTypeExpressionFactory.createTypeVariable(SymTypeExpressionDeSer .resolveTypeVarSymbolOrLogError(varName, enclosingScope)); } Log.error("0x823F5 Internal error: Cannot load \"" + serialized + "\" as SymTypeVariable!"); From b81d69bce6926984037334b0e4db2bc241de043f Mon Sep 17 00:00:00 2001 From: ChrissLue Date: Fri, 2 Oct 2026 14:37:47 +0200 Subject: [PATCH 21/21] reduce __internal__supplier to a pure marker, without implementation and no residuals in the final generated code --- .../codegen/cd2java/DecorationHelper.java | 18 +++++++++-- .../_ast/builder/BuilderDecorator.java | 2 ++ .../BuilderListMutatorDecorator.java | 4 +-- .../scope/ScopeClassDecorator.java | 7 +++-- .../scope/ScopeInterfaceDecorator.java | 5 ++- .../symbol/SymbolBuilderDecorator.java | 2 +- .../_symboltable/symbol/SymbolDecorator.java | 5 ++- .../methods/AccessAsSupplierTypes.java | 3 +- .../_ast/builder/SupplierSet4ASTBuilder.ftl | 2 +- .../builder/SupplierSetRaw4ASTBuilder.ftl | 2 +- .../builder/opt/SupplierSet4ASTBuilderOpt.ftl | 2 +- .../opt/SupplierSetAbsent4ASTBuilderOpt.ftl | 2 +- .../main/resources/methods/SupplierGetRaw.ftl | 2 +- .../main/resources/methods/SupplierSet.ftl | 2 +- .../main/resources/methods/SupplierSetRaw.ftl | 2 +- .../resources/methods/opt/SupplierSet4Opt.ftl | 2 +- .../methods/opt/SupplierSetAbsent.ftl | 2 +- .../scope/ScopeClassDecoratorTest.java | 10 +++--- .../symbol/SymbolBuilderDecoratorTest.java | 6 ++-- .../symbol/SymbolDecoratorTest.java | 8 ++--- .../java/de/monticore/types/MCTypeFacade.java | 23 -------------- .../symboltable/__internal__Supplier.java | 31 ------------------- 22 files changed, 56 insertions(+), 86 deletions(-) delete mode 100644 monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java index 82b36979f6..b62bd8011a 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/DecorationHelper.java @@ -205,9 +205,9 @@ public void addAttributeDefaultValues(ASTCDAttribute attribute, GlobalExtensionM defaultValue = inner; } else if (isList) { // A list must expose a stable instance, otherwise we would create a new one every get and entries would be lost. - defaultValue = "new " + SUPPLIER_TYPE + "<>(com.google.common.base.Suppliers.memoize(() -> " + inner + "))"; + defaultValue = "com.google.common.base.Suppliers.memoize(() -> " + inner + ")"; } else { - defaultValue = "new " + SUPPLIER_TYPE + "<>(() -> " + inner + ")"; + defaultValue = "() -> " + inner; } glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= " + defaultValue)); } @@ -310,10 +310,22 @@ public ASTMCType toPublicSupplierType(ASTMCType type) { return createStdSupplierTypeOf(unwrapSupplier(type)); } + /** + * Replaces the internal marker type of all wrapped attributes by the public {@code java.util.function.Supplier}. + * Must be called after all decorators that rely on {@link #isSupplier} are done with the attributes, because + * afterwards the attributes are no longer recognized as supplied. The generated fields then store the plain supplier. + */ + public void unmarkSuppliers(Collection attributes) { + attributes.stream() + .filter(a -> isSupplier(a.getMCType())) + .forEach(a -> a.setMCType(toPublicSupplierType(a.getMCType()))); + } + /** * Wraps the type of every attribute that {@link #shouldHaveSupplier} selects into the internal supplier type. + * The internal type is only a generation-time marker, see {@link #unmarkSuppliers}. */ - public void wrapSuppliers(Collection attributes) { + public void wrapAndMarkSuppliers(Collection attributes) { attributes.stream() .filter(this::shouldHaveSupplier) .forEach(a -> a.setMCType(createInternalSupplierTypeOf(a.getMCType()))); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java index 1587bd235a..7283fc7652 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/BuilderDecorator.java @@ -117,6 +117,8 @@ public ASTCDClass decorate(final ASTCDClass domainClass) throws DecorateExceptio .collect(Collectors.toList()); builderAttributes.forEach(this::addAttributeDefaultValues); + // the marker type is not needed anymore: the fields store the plain Supplier + getDecorationHelper().unmarkSuppliers(builderAttributes); return CD4AnalysisMill.cDClassBuilder() .setModifier(modifier) diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java index 6effd93ee6..1ce899239f 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_ast/builder/buildermethods/BuilderListMutatorDecorator.java @@ -47,8 +47,8 @@ protected List createSetter(ASTCDAttribute attribute) { String parameterCall = m.getCDParameterList().stream() .map(ASTCDParameter::getName) .collect(Collectors.joining(", ")); - this.replaceTemplate(EMPTY_BODY, m, new TemplateHookPoint("_ast.builder.MethodDelegate4ASTBuilder", - attribute, methodName, parameterCall)); + this.replaceTemplate(EMPTY_BODY, m, new TemplateHookPoint("_ast.builder.MethodDelegate4ASTBuilder", + attribute.deepClone(), methodName, parameterCall)); } return methods; } diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java index 6c1c3e90e3..ca5ed4845d 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecorator.java @@ -96,8 +96,9 @@ public ASTCDClass decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilationUnit .map(ASTCDAttribute::deepClone) .collect(Collectors.toList()); - // Wrap selected scoperule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later - getDecorationHelper().wrapSuppliers(scopeRuleAttributeList); + // Wrap selected scoperule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later. + // Als mark them as special case suppliers + getDecorationHelper().wrapAndMarkSuppliers(scopeRuleAttributeList); scopeRuleAttributeList .forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); @@ -119,6 +120,8 @@ public ASTCDClass decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilationUnit .map(methodDecorator::decorate) .flatMap(List::stream) .collect(Collectors.toList()); + // the marker is not needed anymore: the fields store the plain Supplier + getDecorationHelper().unmarkSuppliers(scopeRuleAttributeList); Map symbolAttributes = createSymbolAttributes( symbolInput.getCDDefinition().getCDClassesList(), symbolTableService.getCDSymbol()); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java index cc4da1297e..447ace65df 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeInterfaceDecorator.java @@ -94,7 +94,10 @@ public ASTCDInterface decorate(ASTCDCompilationUnit scopeInput, ASTCDCompilation .flatMap(List::stream) .map(ASTCDAttribute::deepClone) .collect(Collectors.toList()); - getDecorationHelper().wrapSuppliers(scopeRuleAttributes); + + // Wrap selected scoperule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later. + // Als mark them as special case suppliers. As Interfaces have no attributes, we don't need to unmark later + getDecorationHelper().wrapAndMarkSuppliers(scopeRuleAttributes); List scopeRuleMethodList = scopeInput.deepClone().getCDDefinition().getCDClassesList() .stream() diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java index 1737ed7acb..085836b045 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecorator.java @@ -75,7 +75,7 @@ public ASTCDClass decorate(final ASTCDClass symbolClass) { } } // Wrap selected attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later - getDecorationHelper().wrapSuppliers(decoratedSymbolClass.getCDAttributeList()); + getDecorationHelper().wrapAndMarkSuppliers(decoratedSymbolClass.getCDAttributeList()); builderDecorator.setPrintBuildMethodTemplate(false); ASTCDClass symbolBuilder = builderDecorator.decorate(decoratedSymbolClass); builderDecorator.setPrintBuildMethodTemplate(true); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java index a0ff9251a3..0a3a893573 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecorator.java @@ -92,7 +92,8 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { .collect(Collectors.toList()); // Wrap selected symbolrule attribute types into Supplier so their (possibly not-yet-resolvable) value can be computed later - getDecorationHelper().wrapSuppliers(symbolRuleAttributes); + // Als mark them as special case supplier + getDecorationHelper().wrapAndMarkSuppliers(symbolRuleAttributes); symbolRuleAttributes.forEach(a -> getDecorationHelper().addAttributeDefaultValues(a, this.glex)); List symbolRuleAttributeMethods = symbolRuleAttributes @@ -100,6 +101,8 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { .map(methodDecorator::decorate) .flatMap(List::stream) .collect(Collectors.toList()); + // the marker type is not needed anymore: the fields store the plain Supplier + getDecorationHelper().unmarkSuppliers(symbolRuleAttributes); List symbolRuleMethods = symbolInput.getCDMethodList().stream() .map(ASTCDMethod::deepClone) .collect(Collectors.toList()); diff --git a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java index 1004c7e54c..d4ab40a942 100644 --- a/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java +++ b/monticore-generator/src/main/java/de/monticore/codegen/cd2java/methods/AccessAsSupplierTypes.java @@ -13,7 +13,8 @@ public final class AccessAsSupplierTypes { /** - * Fully qualified name of the wrapper type used for lazily resolved attributes. + * Name of the marker type that tags lazily resolved attributes while the class diagram is decorated. + * There is no implementation. It is only present during decoration. */ public static final String SUPPLIER_TYPE = "de.monticore.symboltable.__internal__Supplier"; diff --git a/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl b/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl index 7e8de17b47..6661b8d21b 100644 --- a/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl +++ b/monticore-generator/src/main/resources/_ast/builder/SupplierSet4ASTBuilder.ftl @@ -1,6 +1,6 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> ${attribute.getName()}); +this.${attribute.getName()} = () -> ${attribute.getName()}; ${defineHookPoint("Setter:After")} return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl index ea6e5d352c..da71c5ff49 100644 --- a/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl +++ b/monticore-generator/src/main/resources/_ast/builder/SupplierSetRaw4ASTBuilder.ftl @@ -1,6 +1,6 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); +this.${attribute.getName()} = ${attribute.getName()}; ${defineHookPoint("Setter:After")} return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl index e56916e5d2..f0a086e4ce 100644 --- a/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl +++ b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSet4ASTBuilderOpt.ftl @@ -1,4 +1,4 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.ofNullable(${attribute.getName()})); +this.${attribute.getName()} = () -> Optional.ofNullable(${attribute.getName()}); return this.realBuilder; diff --git a/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl index e08c2025cd..5e1df9d0ed 100644 --- a/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl +++ b/monticore-generator/src/main/resources/_ast/builder/opt/SupplierSetAbsent4ASTBuilderOpt.ftl @@ -1,4 +1,4 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.empty()); +this.${attribute.getName()} = () -> Optional.empty(); return this.realBuilder; diff --git a/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl index 9a6b96b9fd..1f1de2a52a 100644 --- a/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierGetRaw.ftl @@ -1,3 +1,3 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} -return this.${attribute.getName()}.unwrap(); +return this.${attribute.getName()}; diff --git a/monticore-generator/src/main/resources/methods/SupplierSet.ftl b/monticore-generator/src/main/resources/methods/SupplierSet.ftl index 32a51f6ba6..41e8259e86 100644 --- a/monticore-generator/src/main/resources/methods/SupplierSet.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierSet.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> ${attribute.getName()}); +this.${attribute.getName()} = () -> ${attribute.getName()}; ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl index 5143bf4b97..04c99af220 100644 --- a/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl +++ b/monticore-generator/src/main/resources/methods/SupplierSetRaw.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(${attribute.getName()}); +this.${attribute.getName()} = ${attribute.getName()}; ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl index b0b48853bc..69d9a84eed 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSet4Opt.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute", "nativeAttributeName")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.ofNullable(${attribute.getName()})); +this.${attribute.getName()} = () -> Optional.ofNullable(${attribute.getName()}); ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl index 8a37f755fa..9a899540ca 100644 --- a/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl +++ b/monticore-generator/src/main/resources/methods/opt/SupplierSetAbsent.ftl @@ -1,5 +1,5 @@ <#-- (c) https://github.com/MontiCore/monticore --> ${tc.signature("attribute")} ${defineHookPoint("Setter:Before")} -this.${attribute.getName()} = new de.monticore.symboltable.__internal__Supplier<>(() -> Optional.empty()); +this.${attribute.getName()} = () -> Optional.empty(); ${defineHookPoint("Setter:After")} diff --git a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java index c8431bc5aa..d74c5c1eea 100644 --- a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java +++ b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/scope/ScopeClassDecoratorTest.java @@ -382,27 +382,27 @@ public void testScopeRuleAttributes() { assertBoolean(extraAtt.getMCType()); assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(extraAtt)); - // symType, lSymType and oSymType are of the types listed in AccessAsSupplierTypes, so arewrapped int - // internal Supplier type. + // symType, lSymType and oSymType are of the types listed in AccessAsSupplierTypes, so they are stored as + // plain java.util.function.Supplier. ASTCDAttribute originalSymTypeAttribute = getAttributeBy("symType", originalScopeRuleClass); assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalSymTypeAttribute)); ASTCDAttribute symTypeAttribute = getAttributeBy("symType", scopeClass); assertDeepEquals(PROTECTED, symTypeAttribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalSymTypeAttribute.getMCType()), + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(originalSymTypeAttribute.getMCType()), symTypeAttribute.getMCType()); ASTCDAttribute originalLSymTypeAttribute = getAttributeBy("lSymType", originalScopeRuleClass); assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalLSymTypeAttribute)); ASTCDAttribute lSymTypeAttribute = getAttributeBy("lSymType", scopeClass); assertDeepEquals(PROTECTED, lSymTypeAttribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalLSymTypeAttribute.getMCType()), + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(originalLSymTypeAttribute.getMCType()), lSymTypeAttribute.getMCType()); ASTCDAttribute originalOSymTypeAttribute = getAttributeBy("oSymType", originalScopeRuleClass); assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalOSymTypeAttribute)); ASTCDAttribute oSymTypeAttribute = getAttributeBy("oSymType", scopeClass); assertDeepEquals(PROTECTED, oSymTypeAttribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalOSymTypeAttribute.getMCType()), + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(originalOSymTypeAttribute.getMCType()), oSymTypeAttribute.getMCType()); assertTrue(Log.getFindings().isEmpty()); diff --git a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java index 2ea12e5991..4fa23c6536 100644 --- a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java +++ b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolBuilderDecoratorTest.java @@ -128,7 +128,7 @@ public void testSymTypeAttributeAndMethods() { ASTCDAttribute attribute = getAttributeBy("symType", builderClass); assertDeepEquals(CDModifier.PROTECTED, attribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(symTypeType), attribute.getMCType()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(symTypeType), attribute.getMCType()); ASTCDMethod getter = getMethodBy("getSymType", builderClass); assertDeepEquals(PUBLIC, getter.getModifier()); @@ -164,7 +164,7 @@ public void testLSymTypeAttributeAndMethods() { ASTCDAttribute attribute = getAttributeBy("lSymType", builderClass); assertDeepEquals(CDModifier.PROTECTED, attribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(lSymTypeType), attribute.getMCType()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(lSymTypeType), attribute.getMCType()); ASTCDMethod getter = getMethodBy("getLSymTypeList", builderClass); assertDeepEquals(PUBLIC, getter.getModifier()); @@ -201,7 +201,7 @@ public void testOSymTypeAttributeAndMethods() { ASTCDAttribute attribute = getAttributeBy("oSymType", builderClass); assertDeepEquals(CDModifier.PROTECTED, attribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(oSymTypeType), attribute.getMCType()); + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(oSymTypeType), attribute.getMCType()); ASTCDMethod getter = getMethodBy("getOSymType", builderClass); assertDeepEquals(PUBLIC, getter.getModifier()); diff --git a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java index a1dfdbe523..06605701e1 100644 --- a/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java +++ b/monticore-generator/src/test/java/de/monticore/codegen/cd2java/_symboltable/symbol/SymbolDecoratorTest.java @@ -267,26 +267,26 @@ public void testSymbolRuleAttributes() { assertFalse(AccessAsSupplierTypes.shouldHaveSupplier(extraAtt)); // symType, lSymType and oSymType are of the types listed in AccessAsSupplierTypes, so the - // decorator must wrap their attribute type into the internal Supplier type. + // decorator must store them as a Supplier . ASTCDAttribute originalSymTypeAttribute = getAttributeBy("symType", originalFooClass); assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalSymTypeAttribute)); ASTCDAttribute symTypeAttribute = getAttributeBy("symType", symbolClassFoo); assertDeepEquals(PROTECTED, symTypeAttribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalSymTypeAttribute.getMCType()), + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(originalSymTypeAttribute.getMCType()), symTypeAttribute.getMCType()); ASTCDAttribute originalLSymTypeAttribute = getAttributeBy("lSymType", originalFooClass); assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalLSymTypeAttribute)); ASTCDAttribute lSymTypeAttribute = getAttributeBy("lSymType", symbolClassFoo); assertDeepEquals(PROTECTED, lSymTypeAttribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalLSymTypeAttribute.getMCType()), + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(originalLSymTypeAttribute.getMCType()), lSymTypeAttribute.getMCType()); ASTCDAttribute originalOSymTypeAttribute = getAttributeBy("oSymType", originalFooClass); assertTrue(AccessAsSupplierTypes.shouldHaveSupplier(originalOSymTypeAttribute)); ASTCDAttribute oSymTypeAttribute = getAttributeBy("oSymType", symbolClassFoo); assertDeepEquals(PROTECTED, oSymTypeAttribute.getModifier()); - assertDeepEquals(DecorationHelper.getInstance().createInternalSupplierTypeOf(originalOSymTypeAttribute.getMCType()), + assertDeepEquals(DecorationHelper.getInstance().createStdSupplierTypeOf(originalOSymTypeAttribute.getMCType()), oSymTypeAttribute.getMCType()); assertTrue(Log.getFindings().isEmpty()); diff --git a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java index 24cf2a618f..a3a5809049 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java +++ b/monticore-grammar/src/main/java/de/monticore/types/MCTypeFacade.java @@ -249,29 +249,6 @@ public ASTMCArrayType createArrayType(final String name, int dimension) { return createArrayType(this.createQualifiedType(name), dimension); } - /** - * {@code de.monticore.symboltable.__internal__Supplier} types. - */ - - public ASTMCBasicGenericType createInternalSupplierTypeOf(final ASTMCTypeArgument inner) { - return createBasicGenericTypeOf("de.monticore.symboltable.__internal__Supplier", inner); - } - - public ASTMCBasicGenericType createInternalSupplierTypeOf(final ASTMCType inner) { - ASTMCTypeArgument arg = MCSimpleGenericTypesMill.mCCustomTypeArgumentBuilder() - .setMCType(inner.deepClone()) - .build(); - return createInternalSupplierTypeOf(arg); - } - - public ASTMCBasicGenericType createInternalSupplierTypeOf(final String name) { - return createInternalSupplierTypeOf(createBasicTypeArgumentOf(name)); - } - - public ASTMCBasicGenericType createInternalSupplierTypeOf(final Class clazz) { - return createInternalSupplierTypeOf(clazz.getName()); - } - /** * {@code java.util.function.Supplier } types. */ diff --git a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java b/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java deleted file mode 100644 index a2c60cd5e8..0000000000 --- a/monticore-runtime/src/main/java/de/monticore/symboltable/__internal__Supplier.java +++ /dev/null @@ -1,31 +0,0 @@ -/* (c) https://github.com/MontiCore/monticore */ -package de.monticore.symboltable; - -import java.util.function.Supplier; - -/** - * Internal marker wrapper used by generated symbol classes for symbolrule attributes whose value - * may not be resolvable yet (see {@code AccessAsSupplierTypes} in the generator). - *

- * A dedicated type (instead of a plain {@link Supplier}) is required in case someone wants to actually return a supplier. - */ -public final class __internal__Supplier implements Supplier { - - private final Supplier supplier; - - public __internal__Supplier(Supplier supplier) { - this.supplier = supplier; - } - - @Override - public T get() { - return supplier.get(); - } - - /** - * Returns the supplier this instance wraps. - */ - public Supplier unwrap() { - return supplier; - } -}