diff --git a/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn b/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn index 72c2e0ce954a3071785945bf9027ccc0ac3c48a4..531cd7e9e18281b6c44cde9e710b88980ecedb9e 100755 --- a/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn +++ b/Semantic_Analizer_Tests/src/Basic_tests/OopNegativeSemanticTest.ttcn @@ -86,6 +86,25 @@ type class SubFunctionClass extends BaseFunctionClass { } } +// an abstract class can have a finally block +type class @abstract FinallyClass { + public const integer m_const := 0; +} finally { + log(this); +} + +// a trait class cannot have a finally block +type class @trait FinallyClass2 { + public const integer m_const := 0; +} finally { + log(this); +} + +// bad combination of class modifiers +type class @final @abstract BadClass1 { } +type class @final @trait BadClass3 { } +type class @abstract @trait BadClass2 { } + testcase tc_basicSyntax() runs on CT { var GrandSubClass vl_gsc := GrandSubClass.create; diff --git a/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn b/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn index 210e0f3f3afd73bb86d527d5b0ac20b31b2005f8..a3a824b4ba067628867b6f629424be1ce9efd1e8 100644 --- a/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn +++ b/Semantic_Analizer_Tests/src/Basic_tests/OopPositiveBasicSyntax.ttcn @@ -117,6 +117,13 @@ type class OuterClass { } } +// finally block +type class @abstract FinallyClass { + public const integer m_const := 0; +} finally { + log(this); +} + // `this` reference type class ClassWithThis { public var integer vl_a; diff --git a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java index 4ee4804df0b5d8f6cc86a20262a2b4c2ed9011af..19a23111a94b28d1143f01ebe449b1e6b3067c52 100755 --- a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java +++ b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/AST/TTCN3/types/Class_Type.java @@ -31,6 +31,7 @@ import org.eclipse.titan.designer.AST.Type; import org.eclipse.titan.designer.AST.TypeCompatibilityInfo; import org.eclipse.titan.designer.AST.TypeCompatibilityInfo.Chain; import org.eclipse.titan.designer.AST.TTCN3.Expected_Value_type; +import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock; import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template; import org.eclipse.titan.designer.compiler.JavaGenData; import org.eclipse.titan.designer.parsers.CompilationTimeStamp; @@ -39,7 +40,8 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp; public final class Class_Type extends Type implements ITypeWithComponents { private static final String ABSTRACTCANNOTBEFINAL = "An absract class cannot be final"; private static final String TRAITCANNOTBEFINAL = "A trait class cannot be final"; - private static final String ABSTRACTCANNOTBETRAIT = "An class cannot be both abstract and trait"; + private static final String ABSTRACTCANNOTBETRAIT = "A class cannot be both abstract and trait"; + private static final String TRAITWITHFINALLY = "A trait class should not define a finally block"; private final ClassTypeBody classBody; @@ -47,16 +49,23 @@ public final class Class_Type extends Type implements ITypeWithComponents { private final boolean isFinal; private final boolean isTrait; private final Location modifierLocation; + private final StatementBlock finallyBlock; - public Class_Type(ClassTypeBody classBody, boolean isAbstract, boolean isFinal, boolean isTrait, Location modifierLocation) { + public Class_Type(ClassTypeBody classBody, boolean isAbstract, boolean isFinal, boolean isTrait, Location modifierLocation, StatementBlock finallyBlock) { this.classBody = classBody; this.isAbstract = isAbstract; this.isFinal = isFinal; this.isTrait = isTrait; this.modifierLocation = modifierLocation; + this.finallyBlock = finallyBlock; - classBody.setFullNameParent(this); - classBody.setMyType(this); + if (classBody != null) { + classBody.setFullNameParent(this); + classBody.setMyType(this); + } + if (finallyBlock != null) { + finallyBlock.setFullNameParent(this); + } } @Override @@ -132,6 +141,10 @@ public final class Class_Type extends Type implements ITypeWithComponents { modifierLocation.reportSemanticError(ABSTRACTCANNOTBETRAIT); setIsErroneous(true); } + + if (isTrait && finallyBlock != null) { + finallyBlock.getLocation().reportSemanticError(TRAITWITHFINALLY); + } initAttributes(timestamp); diff --git a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/parsers/ttcn3parser/Ttcn3Parser.g4 b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/parsers/ttcn3parser/Ttcn3Parser.g4 index edd46612ee4feb20acd85838f016c2218766f7aa..bb58b0c036228cdf866a00a0aafdafd0b2ba5f00 100644 --- a/org.eclipse.titan.designer/src/org/eclipse/titan/designer/parsers/ttcn3parser/Ttcn3Parser.g4 +++ b/org.eclipse.titan.designer/src/org/eclipse/titan/designer/parsers/ttcn3parser/Ttcn3Parser.g4 @@ -8974,6 +8974,7 @@ pr_ClassTypeDef returns[Def_Type def_type] boolean isAbstract = false; boolean isFinal = false; boolean isTrait = false; + StatementBlock finallyBlock = null; }: ( ( ext = pr_ExtKeyword )? kw = pr_ClassKeyword @@ -8988,14 +8989,16 @@ pr_ClassTypeDef returns[Def_Type def_type] pr_BeginChar cml = pr_ClassMemberList[$i.identifier, refs] { body = $cml.body; } pr_EndChar - fd = pr_FinallyDef + fd = pr_FinallyDef { + finallyBlock = $fd.statementBlock; + } ) { if ($i.identifier != null) { if (body == null) { body = new ClassTypeBody($i.identifier, refs); } - Type type = new Class_Type(body, isAbstract, isFinal, isTrait, getLocation($kw.stop, $i.start)); + Type type = new Class_Type(body, isAbstract, isFinal, isTrait, getLocation($kw.stop, $i.start), finallyBlock); type.setLocation(getLocation($start, getLastVisibleToken())); $def_type = new Def_Type($i.identifier, type); $def_type.setLocation(getLocation($kw.start, $i.stop)); @@ -9133,10 +9136,15 @@ pr_OopVisibility returns[VisibilityModifier visibility] | PUBLIC { $visibility = VisibilityModifier.Public; } ); -pr_FinallyDef -: +pr_FinallyDef returns[StatementBlock statementBlock] +@init { + $statementBlock = null; +}: ( - FINALLY sb=pr_StatementBlock + FINALLY sb=pr_StatementBlock { + $statementBlock = $sb.statementblock; + $statementBlock.setLocation(getLocation($sb.start, $sb.stop)); + } )?; pr_ClassFunctionDef returns[Def_Function def_func] diff --git a/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java b/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java index 722a8d40250949d86d8541de5b8a30b10e3824b2..db5f01f0b58964af75de224838c888f181a7b3f0 100755 --- a/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java +++ b/org.eclipse.titan.regressiontests/src/org/eclipse/titan/regressiontests/designer/statictests/Basic_tests/OOP_Semantic_tests.java @@ -18,6 +18,10 @@ import org.eclipse.titan.regressiontests.library.MarkerToCheck; import org.junit.BeforeClass; import org.junit.Test; +/** + * @author Miklos Magyari + * @author Adam Knapp + */ public class OOP_Semantic_tests { private static final String DIR_PATH = "src/Basic_tests/"; private static final String OOP_NEGATIVE_BASIC_SEMANTIC = "/OopNegativeSemanticTest.ttcn"; @@ -41,7 +45,7 @@ public class OOP_Semantic_tests { private ArrayList oopNegative_ttcn_initializer() { //oopNegativeSemanticTest.ttcn - ArrayList markersToCheck = new ArrayList(9); + ArrayList markersToCheck = new ArrayList(13); int lineNum = 28; markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR)); lineNum += 15; @@ -54,7 +58,13 @@ public class OOP_Semantic_tests { markersToCheck.add(new MarkerToCheck("integer value was expected", lineNum, IMarker.SEVERITY_ERROR)); lineNum += 4; markersToCheck.add(new MarkerToCheck("Constant must be initialized", lineNum, IMarker.SEVERITY_ERROR)); - lineNum += 17; + lineNum += 20; + markersToCheck.add(new MarkerToCheck("A trait class should not define a finally block", lineNum, IMarker.SEVERITY_ERROR)); + lineNum += 5; + markersToCheck.add(new MarkerToCheck("An absract class cannot be final", lineNum, IMarker.SEVERITY_ERROR)); + markersToCheck.add(new MarkerToCheck("A trait class cannot be final", ++lineNum, IMarker.SEVERITY_ERROR)); + markersToCheck.add(new MarkerToCheck("A class cannot be both abstract and trait", ++lineNum, IMarker.SEVERITY_ERROR)); + lineNum += 9; markersToCheck.add(new MarkerToCheck("There is no visible definition with name `vl_gsc' in module `classesNegativeSemantic'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", ++lineNum, IMarker.SEVERITY_ERROR)); lineNum += 8;