Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import de.monticore.cdinterfaceandenum._ast.ASTCDInterface;
import de.monticore.symbols.oosymbols._symboltable.OOTypeSymbol;
import de.monticore.types.mcbasictypes._ast.ASTMCObjectType;
import de.monticore.types.mcbasictypes._ast.ASTMCQualifiedType;
import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType;
import de.se_rwth.commons.logging.Log;
import java.util.List;
import java.util.Optional;
Expand All @@ -26,14 +28,34 @@ public void check(ASTCDClass node) {
return;
}
final List<ASTMCObjectType> interfaceList = node.getCDInterfaceUsage().getInterfaceList();
interfaceList.stream().map(s -> symbol.getEnclosingScope().resolveOOType(s.printType())).filter(
Optional::isPresent).map(Optional::get).filter(e -> !e.isIsInterface()).forEach(e -> Log
.error(String.format(
interfaceList.stream().map(s -> symbol.getEnclosingScope().resolveOOType(getObjectName(s)))
.filter(Optional::isPresent).map(Optional::get).filter(e -> !e.isIsInterface()).forEach(
e -> Log.error(String.format(
"0xCDCF4: Class %s cannot implement %s %s. A class may only implement interfaces.",
node.getName(), CDMill.cDTypeKindPrinter().print(e), e.getName()), node
.get_SourcePositionStart()));
}

protected String getObjectName(ASTMCObjectType type) {
// TODO: This is a fix for the following types:
// class State_Pat implements IState, IElem<IState>
// class Opt<T> implements IElem<T>
// interface IElem<T> { }
// -> this tries to resolve "IElem<T>.class", which fails HARD due to illegal chars!
// TODO: Discuss where to place such a thing

if (type instanceof ASTMCQualifiedType qualifiedType) {
return qualifiedType.getMCQualifiedName().getQName();
}
else if (type instanceof ASTMCGenericType genericType) {
return genericType.printWithoutTypeArguments();
}
else {
throw new IllegalStateException("Unhandled MCObjectType " + type.getClass() + " of `" + type
.printType() + "` when trying to resolve source");
}
}

/**
* Actual check that the enums interfaces are really interfaces.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public ChainableGenSetup withMethodImplementations() {
return this.withDecorator(new MethodImplementationDecorator());
}

public ChainableGenSetup withRequiredArgsConstructors() {
return this.withDecorator(new RequiredArgsConstructorDecorator());
}

@SuppressWarnings("unchecked")
public ChainableGenSetup withDecorator(String className) {
IDecorator<?> newObj = (IDecorator<?>) ObjectFactory.createObject(className);
Expand Down
39 changes: 39 additions & 0 deletions cdlang/src/main/java/de/monticore/cd/codegen/MCTypeFacadeFix.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.cd.codegen;

import com.google.common.collect.Lists;
import de.monticore.cd4code.CD4CodeMill;
import de.monticore.types.mcbasictypes._ast.ASTMCType;
import de.monticore.types.mccollectiontypes._ast.ASTMCGenericType;
import de.monticore.types.mccollectiontypes._ast.ASTMCListType;
import de.monticore.types.mccollectiontypes._ast.ASTMCSetType;
import de.monticore.types.mcfullgenerictypes.MCFullGenericTypesMill;

// TODO: Move this fix upstream if MCFullGenericTypes (?) is initialized
public class MCTypeFacadeFix {

public static ASTMCListType createListTypeOf(final ASTMCType type) {
// Fix for IElem<IStateElem>
var b = MCFullGenericTypesMill.mCListTypeBuilder();
b.setMCTypeArgument(CD4CodeMill.mCCustomTypeArgumentBuilder().setMCType(type.deepClone())
.build());
return b.build();
}

public static ASTMCSetType createSetTypeOf(final ASTMCType type) {
// Fix for IElem<IStateElem>
var b = MCFullGenericTypesMill.mCSetTypeBuilder();
b.setMCTypeArgument(CD4CodeMill.mCCustomTypeArgumentBuilder().setMCType(type.deepClone())
.build());
return b.build();
}

public ASTMCGenericType createCollectionTypeOf(final ASTMCType type) {
var b = MCFullGenericTypesMill.mCBasicGenericTypeBuilder();
b.setNamesList(Lists.newArrayList("Collection"));
b.addMCTypeArgument(CD4CodeMill.mCCustomTypeArgumentBuilder().setMCType(type.deepClone())
.build());
return b.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY;

import com.google.common.collect.Iterables;
import de.monticore.cd.codegen.decorators.data.AbstractDecorator;
import de.monticore.cd.facade.CDConstructorFacade;
import de.monticore.cd4code._visitor.CD4CodeTraverser;
Expand Down Expand Up @@ -77,7 +78,7 @@ protected void decorateList(ASTCDClass decoratedClazz, ASTCDAttribute attribute)
// Setting the initial value of the attribute fails, as
// "new"/CreatorExpression is not part of CD4C
glex.addAfterTemplate(EMPTY_BODY, c, new TemplateHookPoint("methods.Instantiation", attribute
.getName(), ArrayList.class.getName()))));
.getName(), ArrayList.class.getName() + "<>"))));
}

protected ASTModifier createModifier(ASTModifier original) {
Expand All @@ -103,4 +104,11 @@ public void addToTraverser(CD4CodeTraverser traverser) {
traverser.add4CDBasis(this);
}

@Override
public Iterable<Class<? extends IDecorator>> getMustRunAfter() {
// Constructors may be added here
return Iterables.concat(super.getMustRunAfter(), List.of(
RequiredArgsConstructorDecorator.class));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import static de.monticore.cd.codegen.CD2JavaTemplates.EMPTY_BODY;

import de.monticore.cd.codegen.MCTypeFacadeFix;
import de.monticore.cd.codegen.decorators.data.AbstractDecorator;
import de.monticore.cd.codegen.decorators.data.DecoratorData;
import de.monticore.cd.facade.CDMethodFacade;
Expand Down Expand Up @@ -130,7 +131,7 @@ protected MethodInformation decorateSet(ASTCDType decoratedType, ASTCDAttribute
ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone();

ASTCDMethod getListMethod = CDMethodFacade.getInstance().createMethod(attribute.getModifier()
.deepClone(), MCTypeFacade.getInstance().createSetTypeOf(type), name);
.deepClone(), MCTypeFacadeFix.createSetTypeOf(type), name);
glexOpt.ifPresent(glex -> glex.replaceTemplate(EMPTY_BODY, getListMethod, new TemplateHookPoint(
"methods.Get", attribute)));
getListMethod.getModifier().setAbstract(attribute.getModifier().isDerived());
Expand All @@ -147,7 +148,7 @@ protected MethodInformation decorateList(ASTCDType decoratedType, ASTCDAttribute
ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone();

ASTCDMethod getListMethod = CDMethodFacade.getInstance().createMethod(attribute.getModifier()
.deepClone(), MCTypeFacade.getInstance().createListTypeOf(type), name);
.deepClone(), MCTypeFacadeFix.createListTypeOf(type), name);
glexOpt.ifPresent(glex -> glex.replaceTemplate(EMPTY_BODY, getListMethod, new TemplateHookPoint(
"methods.Get", attribute)));
getListMethod.getModifier().setAbstract(attribute.getModifier().isDerived());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,23 @@
if (decoratorData.shouldDecorate(this.getClass(), method)) {
// Then ensure a stereotype is present (as we do not support other configuration values so far)
if (!method.getModifier().isPresentStereotype()) {
Log.error("0xTODO: The method " + method.getName()

Check warning on line 25 in cdlang/src/main/java/de/monticore/cd/codegen/decorators/MethodImplementationDecorator.java

View workflow job for this annotation

GitHub Actions / check-error-codes

ErrorCodeInvalid

Invalid error code 0xTODO (./cdlang/src/main/java/de/monticore/cd/codegen/decorators/MethodImplementationDecorator.java:25)
+ " is decorated with a method implementation, but does not present a stereotype.",
method.get_SourcePositionStart(), method.get_SourcePositionEnd());
return;
}

// TODO: ALu: Create shared get-marked value source (not only for stereotypes)
String template = method.getModifier().getStereotype().getValue("impl");

// TODO: Discuss if split via # or separate stereo is better for params?
String[] sp = method.getModifier().getStereotype().getValue("impl").split("#");
String template = sp[0];
Object[] templateParams = new Object[sp.length - 1];
System.arraycopy(sp, 1, templateParams, 0, sp.length - 1);

// And finally. replace the empty body template with the given template
glexOpt.ifPresent(g -> g.replaceTemplate(CD4C.getInstance().getEmptyBodyTemplate(),
decoratorData.getAsDecorated(method), new TemplateHookPoint(template)));
decoratorData.getAsDecorated(method), new TemplateHookPoint(template, templateParams)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import com.google.common.collect.Iterables;
import de.monticore.ast.ASTNode;
import de.monticore.cd.codegen.MCTypeFacadeFix;
import de.monticore.cd.codegen.decorators.data.AbstractDecorator;
import de.monticore.cd.facade.CDMethodFacade;
import de.monticore.cd.facade.CDParameterFacade;
Expand Down Expand Up @@ -72,7 +73,7 @@
{
//create an attribute of the type and the name of an observer
ASTCDAttribute observerList = CD4CodeMill.cDAttributeBuilder().setName(OBS_LIST_ATTR)
.setMCType(MCTypeFacade.getInstance().createListTypeOf(observerInterfaceQualifiedType))
.setMCType(MCTypeFacadeFix.createListTypeOf(observerInterfaceQualifiedType))
.setModifier(CD4CodeMill.modifierBuilder().PROTECTED().build()).build();
decClazz.addCDMember(observerList);

Expand Down Expand Up @@ -220,7 +221,7 @@
}
break;
default:
Log.warn("0xTODO: Unexpected method kind " + mi.getKind(), attribute

Check warning on line 224 in cdlang/src/main/java/de/monticore/cd/codegen/decorators/ObserverDecorator.java

View workflow job for this annotation

GitHub Actions / check-error-codes

ErrorCodeInvalid

Invalid error code 0xTODO (./cdlang/src/main/java/de/monticore/cd/codegen/decorators/ObserverDecorator.java:224)
.get_SourcePositionStart());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.cd.codegen.decorators;

import de.monticore.cd.codegen.decorators.data.AbstractDecorator;
import de.monticore.cd.facade.CDConstructorFacade;
import de.monticore.cd.facade.CDParameterFacade;
import de.monticore.cd.methodtemplates.CD4C;
import de.monticore.cd4code._visitor.CD4CodeTraverser;
import de.monticore.cd4codebasis._ast.ASTCDConstructor;
import de.monticore.cd4codebasis._visitor.CD4CodeBasisVisitor2;
import de.monticore.cdbasis._ast.ASTCDAttribute;
import de.monticore.cdbasis._ast.ASTCDClass;
import de.monticore.cdbasis._visitor.CDBasisVisitor2;
import de.monticore.generating.templateengine.TemplateHookPoint;
import de.monticore.umlmodifier.UMLModifierMill;
import de.monticore.umlmodifier._ast.ASTModifier;
import de.monticore.umlmodifier._ast.ASTModifierBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
* Provides method bodies of (modeled) methods from templates
* TODO: ALu - Add CI tests for this decorator (right now it is for playing around)
*/
public class RequiredArgsConstructorDecorator extends AbstractDecorator<AbstractDecorator.NoData>
implements CD4CodeBasisVisitor2, CDBasisVisitor2 {

protected record StackData(List<ASTCDAttribute> attrs) {}

protected Stack<StackData> stack = new Stack<>();

@Override
public void visit(ASTCDClass astcdClass) {
stack.push(new StackData(new ArrayList<>()));
}

@Override
public void visit(ASTCDAttribute attribute) {
if (stack.isEmpty())
return;

// TODO: required vs all?
if (!attribute.getModifier().isFinal())
return;

if (decoratorData.shouldDecorate(this.getClass(), attribute))
stack.peek().attrs.add(attribute);
}

@Override
public void endVisit(ASTCDClass node) {
if (stack.isEmpty())
return;
if (decoratorData.shouldDecorate(this.getClass(), node)) {
// TODO: Check that method does not already exists!
ASTCDConstructor constructor = CDConstructorFacade.getInstance().createConstructor(
copyVisibility(node.getModifier()), node.getName());
for (ASTCDAttribute attribute : stack.peek().attrs()) {
constructor.addCDParameter(CDParameterFacade.getInstance().createParameter(attribute));
}

decoratorData.getAsDecorated(node).addCDMember(constructor);

glexOpt.ifPresent(g -> g.replaceTemplate(CD4C.getInstance().getEmptyBodyTemplate(),
constructor, new TemplateHookPoint("methods.constructor.Constructor", stack
.peek().attrs)));

stack.pop();
}
}

protected ASTModifier copyVisibility(ASTModifier orig) {
ASTModifierBuilder vis = UMLModifierMill.modifierBuilder();
vis.setPublic(orig.isPublic());
vis.setProtected(orig.isProtected());
vis.setPrivate(orig.isPrivate());
return vis.build();
}

@Override
public void addToTraverser(CD4CodeTraverser traverser) {
traverser.add4CD4CodeBasis(this);
traverser.add4CDBasis(this);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import de.monticore.cd4codebasis._ast.ASTCDInterface;
import de.monticore.cd4codebasis._ast.ASTCDMethod;
import de.monticore.cd4codebasis._ast.ASTCDParameter;
import de.monticore.cdbasis._ast.ASTCDClass;
import de.monticore.cdbasis._ast.ASTCDDefinition;
import de.monticore.cdbasis._ast.ASTCDType;
import de.monticore.cdbasis._visitor.CDBasisVisitor2;
import de.monticore.generating.templateengine.TemplateHookPoint;
import de.monticore.types.MCTypeFacade;
Expand Down Expand Up @@ -78,10 +78,10 @@ public void endVisit(ASTCDDefinition clazz) {
}

@Override
public void visit(ASTCDClass clazz) {
if (decoratorData.shouldDecorate(this.getClass(), clazz)) {
ASTCDClass decClazz = decoratorData.getAsDecorated(clazz);
String packageName = clazz.getSymbol().getPackageName();
public void visit(ASTCDType type) {
if (decoratorData.shouldDecorate(this.getClass(), type)) {
ASTCDType decClazz = decoratorData.getAsDecorated(type);
String packageName = type.getSymbol().getPackageName();

ASTCDInterface visitorInterface = getVisitorInterface();

Expand All @@ -93,7 +93,7 @@ public void visit(ASTCDClass clazz) {
ASTCDParameter visitorParameter = CD4CodeMill.cDParameterBuilder().setName("visitor")
.setMCType(visitorInterfaceQualifiedType).build();
//create a type of the class
ASTMCType classType = MCTypeFacade.getInstance().createQualifiedType(clazz.getName());
ASTMCType classType = MCTypeFacade.getInstance().createQualifiedType(type.getName());
ASTCDParameter classParameter = CD4CodeMill.cDParameterBuilder().setName("node").setMCType(
classType).build();

Expand All @@ -104,8 +104,7 @@ public void visit(ASTCDClass clazz) {
// add the interface methods to the pojo class
addToClass(decClazz, acceptMethod);
glexOpt.ifPresent(glex -> glex.replaceTemplate(EMPTY_BODY, acceptMethod,
new TemplateHookPoint("methods.visitor.Accept", clazz.getName())));
// new StringHookPoint("visitor.visit ((" + clazz.getName() + ")this);")));
new TemplateHookPoint("methods.visitor.Accept", type.getName())));

CD4C.getInstance().addImport(decClazz, visitorInterfaceName);
this.decParent.push(decClazz);
Expand All @@ -118,13 +117,13 @@ public void visit(ASTCDClass clazz) {
}

@Override
public void endVisit(ASTCDClass clazz) {
public void endVisit(ASTCDType clazz) {
if (decoratorData.shouldDecorate(this.getClass(), clazz)) {
decParent.pop();
}
}

protected Stack<ASTCDClass> decParent = new Stack<>();
protected Stack<ASTCDType> decParent = new Stack<>();

@Override
public void addToTraverser(CD4CodeTraverser traverser) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import de.monticore.cd.facade.CDMethodFacade;
import de.monticore.cd4code.CD4CodeMill;
import de.monticore.cd4code._visitor.CD4CodeTraverser;
import de.monticore.cd4codebasis._ast.ASTCDInterface;
import de.monticore.cd4codebasis._ast.ASTCDMethod;
import de.monticore.cd4codebasis._ast.ASTCDParameter;
import de.monticore.cd4codebasis._visitor.CD4CodeBasisVisitor2;
import de.monticore.cdbasis._ast.ASTCDAttribute;
import de.monticore.cdbasis._ast.ASTCDClass;
import de.monticore.cdbasis._ast.ASTCDDefinition;
Expand All @@ -34,7 +36,7 @@
* Applies the Visitor-Pattern to the CD
*/
public class VisitorImplementationDecorator extends AbstractDecorator<AbstractDecorator.NoData>
implements CDBasisVisitor2 {
implements CDBasisVisitor2, CD4CodeBasisVisitor2 {

protected GetterDecorator.GetterData getterData;

Expand Down Expand Up @@ -146,7 +148,7 @@
if (attrInfo.getSymTypeExpression().getTypeInfo().isPresentAstNode() && !decoratorData
.shouldDecorate(VisitorDecorator.class, attrInfo.getSymTypeExpression().getTypeInfo()
.getAstNode())) {
warn(attribute, "0xTODO: Visitor implementation of association `" + attribute.getSymbol()

Check warning on line 151 in cdlang/src/main/java/de/monticore/cd/codegen/decorators/VisitorImplementationDecorator.java

View workflow job for this annotation

GitHub Actions / check-error-codes

ErrorCodeInvalid

Invalid error code 0xTODO (./cdlang/src/main/java/de/monticore/cd/codegen/decorators/VisitorImplementationDecorator.java:151)
.getFullName() + "` is not possible due to missing visitor of the class `" + attrInfo
.getSymTypeExpression().getTypeInfo().getFullName() + "`");
return;
Expand Down Expand Up @@ -197,7 +199,7 @@
}

protected void warnMissingGetter(ASTCDAttribute attribute) {
String message = "0xTODO: Attribute `" + attribute.getSymbol().getFullName()

Check warning on line 202 in cdlang/src/main/java/de/monticore/cd/codegen/decorators/VisitorImplementationDecorator.java

View workflow job for this annotation

GitHub Actions / check-error-codes

ErrorCodeInvalid

Invalid error code 0xTODO (./cdlang/src/main/java/de/monticore/cd/codegen/decorators/VisitorImplementationDecorator.java:202)
+ "` has no getter information provided. Unable to include in "
+ getVisitorImplementationClass().getName();
warn(attribute, message);
Expand All @@ -217,12 +219,30 @@
}
}

@Override
public void visit(ASTCDInterface cdInterface) {
if (decoratorData.shouldDecorate(this.getClass(), cdInterface)) {
ASTMCType classType = MCTypeFacade.getInstance().createQualifiedType(cdInterface.getName());
ASTCDParameter classParameter = CD4CodeMill.cDParameterBuilder().setName("node").setMCType(
classType).build();

// add visit method
ASTCDMethod visitMethod = CDMethodFacade.getInstance().createMethod(CD4CodeMill
.modifierBuilder().PUBLIC().build(), "visit", classParameter);
getVisitorImplementationClass().addCDMember(visitMethod);
glexOpt.ifPresent(glex -> glex.replaceTemplate(EMPTY_BODY, visitMethod, new TemplateHookPoint(
"methods.visitor.DefaultVisit", (Object) null)));

}
}

protected Stack<ASTCDMethod> visitMethodStack = new Stack<>();
protected Stack<ASTCDClass> decParent = new Stack<>();

@Override
public void addToTraverser(CD4CodeTraverser traverser) {
traverser.add4CDBasis(this);
traverser.add4CD4CodeBasis(this);
}

}
Loading
Loading