-
Notifications
You must be signed in to change notification settings - Fork 30
SymTypeExpression and wrappers return a supplier in case the symbol c… #372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
SE-FDr
wants to merge
23
commits into
MontiCore:dev
Choose a base branch
from
Chrisslue:add-supplier
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,564
−397
Draft
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
741ad34
SymTypeExpression and wrappers return a supplier in case the symbol c…
Chrisslue d590008
PR feedback
Chrisslue 3982a02
use __internal__Supplier
Chrisslue 8526745
supplierGet now warn instead if throwing
Chrisslue bd04066
spike through SymTypeOfObject now uses supplier
Chrisslue 91f492d
Revert "spike through SymTypeOfObject now uses supplier"
Chrisslue 437fe93
SymTypeExpression and wrappers return a supplier in case the symbol c…
Chrisslue 8f29bd2
PR feedback
Chrisslue 6aa41fa
use __internal__Supplier
Chrisslue 48fee8d
supplierGet now warn instead if throwing
Chrisslue 20bed4b
rebase
Chrisslue 2e7007e
Revert "spike through SymTypeOfObject now uses supplier"
Chrisslue b97dc96
Merge remote-tracking branch 'origin/add-supplier' into add-supplier
Chrisslue 09cb397
broken
Chrisslue 58c28a6
Builder can use supplier
Chrisslue 3b7a68d
removed suppliers from SymTypeExpression desers
Chrisslue c7d3848
Merge upstream/dev into add-supplier
Chrisslue e02cd6d
extracted duplicate code:
Chrisslue 22c7377
make all the decorator look the same (don't want to pull out a functi…
Chrisslue 0993d94
tests for new decorations
Chrisslue 396e9b5
tests for new decorations
Chrisslue 8ac98c6
moved resolveOrLogError to out of factory
Chrisslue b81d69b
reduce __internal__supplier to a pure marker, without implementation …
Chrisslue File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,15 +9,17 @@ | |
| 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; | ||
| import de.monticore.types.MCBasicTypesHelper; | ||
| import de.monticore.types.MCTypeFacade; | ||
| 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; | ||
|
|
@@ -26,11 +28,14 @@ | |
| 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 { | ||
|
|
||
|
|
@@ -67,15 +72,15 @@ 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) { | ||
| return isOptional(attr.getMCType()) && isAstNode(attr); | ||
| } | ||
|
|
||
| public boolean isListAstNode(ASTCDAttribute attribute) { | ||
| return isListType(attribute.printType()) && isAstNode(attribute); | ||
| return isList(attribute.getMCType()) && isAstNode(attribute); | ||
| } | ||
|
|
||
| public boolean isListType(String type) { | ||
|
|
@@ -100,17 +105,36 @@ 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)); | ||
| /** | ||
| * 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 false; | ||
| 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. | ||
| public boolean isOptional(ASTMCType type) { | ||
| return isOptional(type.printType()); | ||
| } | ||
|
|
||
| public boolean isList(ASTMCType type) { | ||
| return isListType(type.printType()); | ||
| } | ||
|
|
||
| public boolean isSupplier(ASTMCType type) { | ||
| return isSupplier(type.printType()); | ||
| } | ||
|
|
||
| public boolean shouldHaveSupplier(ASTCDAttribute attribute) { | ||
| return AccessAsSupplierTypes.shouldHaveSupplier(attribute); | ||
| } | ||
|
|
||
| public boolean isString(String type) { | ||
|
|
@@ -159,12 +183,33 @@ 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<X>) the default is derived from the unwrapped type X. | ||
| boolean isSupplier = isSupplier(attribute.getMCType()); | ||
| ASTMCType type = unwrapSupplier(attribute.getMCType()); | ||
|
|
||
| boolean isList = isList(type); | ||
| String inner; | ||
| if (isList) { | ||
| inner = "new java.util.ArrayList<>()"; | ||
| } else if (isOptional(type)) { | ||
| inner = "Optional.empty()"; | ||
| } else if (isSupplier) { | ||
| inner = "null"; | ||
| } else { | ||
| return; | ||
| } | ||
|
|
||
| } else if (isOptional(attribute.getMCType())) { | ||
| glex.replaceTemplate(VALUE, attribute, new StringHookPoint("= Optional.empty()")); | ||
| // the initialization expression that is placed after the '=' of the field declaration | ||
| String 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)); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -179,11 +224,38 @@ 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 getReferenceTypeOfSupplier(ASTMCType type) { | ||
| Preconditions.checkArgument(isSupplier(type)); | ||
| return ((ASTMCGenericType) type).getMCTypeArgumentList().getFirst(); | ||
| } | ||
|
|
||
| /** | ||
| * Wraps {@code inner} into the internal supplier type {@code __internal__Supplier<inner>} | ||
| * | ||
| * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... | ||
| */ | ||
| 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 public {@code java.util.function.Supplier<inner>} type. | ||
| * | ||
| * A copy of this is already in the MCTypeFacade. This can be deleted, and references rerouted to MCTypeFacade after release ... | ||
| */ | ||
| public ASTMCType createStdSupplierTypeOf(ASTMCType inner) { | ||
| ASTMCTypeArgument arg = MCSimpleGenericTypesMill | ||
| .mCCustomTypeArgumentBuilder().setMCType(inner.deepClone()).build(); | ||
| return MCTypeFacade.getInstance().createBasicGenericTypeOf(STD_SUPPLIER_TYPE, arg); | ||
| } | ||
|
|
||
| /** | ||
| * methods only used in templates | ||
| */ | ||
|
|
@@ -219,12 +291,52 @@ 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; | ||
| } | ||
|
|
||
| /** | ||
| * The type that generated code exposes for a supplied attribute: | ||
| * {@code __internal__Supplier<X>} (or an unwrapped X) becomes {@code java.util.function.Supplier<X>}, | ||
| * so the internal wrapper never leaks into the public API. | ||
| */ | ||
| public ASTMCType toPublicSupplierType(ASTMCType type) { | ||
| return createStdSupplierTypeOf(unwrapSupplier(type)); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes me wonder if the setup is too complex. |
||
| } | ||
|
|
||
| /** | ||
| * Replaces the internal marker type of all wrapped attributes by the public {@code java.util.function.Supplier<X>}. | ||
| * 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<ASTCDAttribute> 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 wrapAndMarkSuppliers(Collection<ASTCDAttribute> 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 | ||
| */ | ||
| 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")) { | ||
|
|
@@ -247,7 +359,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(), | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
defaultValueis what comes after the=.This is more like the
defaultInitializationor simmilar?