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 4da4f43410..1e90ba4690 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 @@ -153,6 +153,10 @@ public ASTCDClass decorate(ASTCDClass symbolInput) { .addCDMember(createDetermineFullName(scopeInterface)) .build(); + // Only add a toString method, if not already present on the input CD + if (symbolClass.getCDMethodList().stream().noneMatch(x->x.getName().equals("toString") && x.getCDParameterList().isEmpty())) + symbolClass.addCDMember(createToString(symbolName)); + // add only for scope spanning symbols if (hasScope || hasInheritedScope) { ASTCDAttribute spannedScopeAttribute = createSpannedScopeAttribute(); @@ -314,6 +318,15 @@ protected ASTCDMethod createDetermineFullName(String scopeInterface) { return method; } + protected ASTCDMethod createToString(String symbolName) { + ASTMCType stringType = getMCTypeFacade().createStringType(); + + ASTCDMethod method = getCDMethodFacade().createMethod(PUBLIC.build(), stringType, "toString"); + this.replaceTemplate(EMPTY_BODY, method, new TemplateHookPoint(TEMPLATE_PATH + "ToString", + symbolName)); + return method; + } + public boolean isSymbolTop() { return isSymbolTop; } diff --git a/monticore-generator/src/main/resources/_symboltable/symbol/ToString.ftl b/monticore-generator/src/main/resources/_symboltable/symbol/ToString.ftl new file mode 100644 index 0000000000..926a01bd8c --- /dev/null +++ b/monticore-generator/src/main/resources/_symboltable/symbol/ToString.ftl @@ -0,0 +1,6 @@ + <#-- (c) https://github.com/MontiCore/monticore --> +${tc.signature("symbolName")} +return "${symbolName}{" + + "fullName='" + this.getFullName() + "'" + + ", sourcePosition=" + this.getSourcePosition() + +'}'; 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 a6441af4da..d69538846c 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 @@ -244,7 +244,7 @@ public void testSymbolRuleAttributes() { @Test public void testMethods() { - assertEquals(20, symbolClassAutomaton.getCDMethodList().size()); + assertEquals(21, symbolClassAutomaton.getCDMethodList().size()); } @Test @@ -559,7 +559,7 @@ public void testSpannedScopeAttributeStateSymbol() { @Test public void testMethodsStateSymbol() { - assertEquals(18, symbolClassState.getCDMethodList().size()); + assertEquals(19, symbolClassState.getCDMethodList().size()); assertTrue(Log.getFindings().isEmpty()); } @@ -655,7 +655,7 @@ public void testScopeRuleMethod() { assertDeepEquals(String.class, method.getMCReturnType().getMCType()); assertTrue(method.isEmptyCDParameters()); - + assertTrue(Log.getFindings().isEmpty()); } diff --git a/monticore-test/02.experiments/symbols/src/test/java/AutomataSymbolsTest.java b/monticore-test/02.experiments/symbols/src/test/java/AutomataSymbolsTest.java index 22afea92bb..ce6caf50b7 100644 --- a/monticore-test/02.experiments/symbols/src/test/java/AutomataSymbolsTest.java +++ b/monticore-test/02.experiments/symbols/src/test/java/AutomataSymbolsTest.java @@ -51,6 +51,8 @@ public void testStateSymbol1() throws IOException { assertEquals("ping",s1.getName()); assertEquals("",s1.getPackageName()); assertEquals("ping",s1.getFullName()); + // Test the generated toString method() + assertEquals("StateSymbol{fullName='ping', sourcePosition=<0,0>}",s1.toString()); assertTrue(Log.getFindings().isEmpty()); }