Commit 1291d980 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: semantic check - trait classes can only declare abstract methods (issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 5a37ec92
......@@ -54,8 +54,9 @@ type class @trait BadTraitClass {
var float vl_float := 1.0;
}
private function f_valid(integer pl_int);
private function f_invalid(integer pl_int) {
private function @abstract f_valid(integer pl_int);
public function f_invalid_non_abstract(in charstring pl_cstr);
private function @abstract f_invalid(integer pl_int) {
// this should not be here
}
......
......@@ -83,6 +83,10 @@ type class MembersClass {
}
}
type class TraitClass {
public function @abstract f_func(in integer pl_in);
}
type union MyUnion {
integer choice1,
charstring choice2
......
......@@ -135,7 +135,10 @@ public final class Def_Function extends Definition implements IParameterisedAssi
private EncodingPrototype_type prototype;
private Type inputType;
private Type outputType;
private final boolean isClassFunction;
private final boolean isAbstract;
private final boolean isFinal;
// stores whether this function can be started or not
private boolean isStartable;
......@@ -144,7 +147,8 @@ public final class Def_Function extends Definition implements IParameterisedAssi
public Def_Function(final Identifier identifier, final FormalParameterList formalParameters, final Reference runsOnRef,
final Reference mtcReference, final Reference systemReference, final Reference portReference,
final Type returnType, final boolean returnsTemplate, final TemplateRestriction.Restriction_type templateRestriction,
final StatementBlock block, boolean isClassFunction) {
final StatementBlock block,
boolean isClassFunction, boolean isAbstract, boolean isFinal) {
super(identifier);
assignmentType = (returnType == null) ? Assignment_type.A_FUNCTION : (returnsTemplate ? Assignment_type.A_FUNCTION_RTEMP
: Assignment_type.A_FUNCTION_RVAL);
......@@ -162,6 +166,8 @@ public final class Def_Function extends Definition implements IParameterisedAssi
this.templateRestriction = templateRestriction;
this.block = block;
this.isClassFunction = isClassFunction;
this.isAbstract = isAbstract;
this.isFinal = isFinal;
this.prototype = EncodingPrototype_type.NONE;
inputType = null;
......@@ -194,7 +200,7 @@ public final class Def_Function extends Definition implements IParameterisedAssi
final Type returnType, final boolean returnsTemplate, final TemplateRestriction.Restriction_type templateRestriction,
final StatementBlock block) {
this(identifier, formalParameters, runsOnRef, mtcReference, systemReference, portReference, returnType,
returnsTemplate, templateRestriction, block, false);
returnsTemplate, templateRestriction, block, false, false, false);
}
/**
......@@ -373,6 +379,14 @@ public final class Def_Function extends Definition implements IParameterisedAssi
return portType;
}
public boolean isAbstract() {
return isAbstract;
}
public boolean isFinal() {
return isFinal;
}
@Override
/** {@inheritDoc} */
......
......@@ -59,6 +59,7 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
public static final String TRAITMETHODSONLY = "Trait classes can only declare methods";
public static final String TRAITMETHODHASBODY = "Trait method cannot have a function body";
public static final String TRAITCONSTRUCTOR = "Trait classes cannot have a constructor";
public static final String TRAITMETHODABSTRACT = "Trait classes can only declare abstract methods";
private final Identifier identifier;
/** The class's own definitions */
......@@ -361,9 +362,14 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
def.getLocation().reportSingularSemanticError(TRAITCONSTRUCTOR);
myType.setIsErroneous(true);
}
else if (funcDef.hasBody()) {
def.getLocation().reportSingularSemanticError(TRAITMETHODHASBODY);
myType.setIsErroneous(true);
else {
if (! funcDef.isAbstract()) {
def.getLocation().reportSingularSemanticError(TRAITMETHODABSTRACT);
}
if (funcDef.hasBody()) {
def.getLocation().reportSingularSemanticError(TRAITMETHODHASBODY);
myType.setIsErroneous(true);
}
}
} else {
def.getLocation().reportSingularSemanticError(TRAITMETHODSONLY);
......
......@@ -9196,7 +9196,8 @@ pr_ClassFunctionDef returns[Def_Function def_func]
(
pr_ExtKeyword?
col = pr_FunctionKeyword
mod = pr_Modifier[isAbstract, isFinal, isTrait]
( fm = pr_FinalModifier { isFinal = $fm.isFinal; } )?
( am = pr_AbstractModifier { isAbstract = $am.isAbstract; } )?
pr_DeterministicModifier?
id = pr_Identifier
start1 = pr_LParen
......@@ -9222,7 +9223,7 @@ pr_ClassFunctionDef returns[Def_Function def_func]
if($id.identifier != null) {
if(parameters == null) { parameters = new FormalParameterList(new ArrayList<FormalParameter>()); }
parameters.setLocation(getLocation( $start1.start, $end.stop));
$def_func = new Def_Function($id.identifier, parameters, runsonHelper.runsonReference, runsonHelper.mtcReference, runsonHelper.systemReference, portReference, returnType, returnsTemplate, templateRestriction, statementBlock, true);
$def_func = new Def_Function($id.identifier, parameters, runsonHelper.runsonReference, runsonHelper.mtcReference, runsonHelper.systemReference, portReference, returnType, returnsTemplate, templateRestriction, statementBlock, true, isAbstract, isFinal);
$def_func.setLocation(getLocation( $col.start, $sb.stop));
$def_func.setCommentLocation( getLastCommentLocation( $start ) );
}
......@@ -9260,7 +9261,7 @@ pr_ClassConstructorDef returns[Def_Function def_func]
if(parameters == null) { parameters = new FormalParameterList(new ArrayList<FormalParameter>()); }
parameters.setLocation(getLocation( $pstart.start, $pstop.stop));
Identifier id = new Identifier( Identifier_type.ID_TTCN, "create", getLocation($id.start, $id.stop ) );
$def_func = new Def_Function(id, parameters, null, null, null, null, null, false, null, statementBlock, true);
$def_func = new Def_Function(id, parameters, null, null, null, null, null, false, null, statementBlock, true, false, false);
$def_func.setLocation(getLocation( $id.start, $sb.stop));
$def_func.setCommentLocation( getLastCommentLocation( $start ) );
};
......
......@@ -45,7 +45,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(39);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(41);
int lineNum = 28;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 9;
......@@ -64,7 +64,8 @@ public class OOP_Semantic_tests {
}
markersToCheck.add(new MarkerToCheck("Trait classes cannot have a constructor", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 5;
markersToCheck.add(new MarkerToCheck("Trait method cannot have a function body", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Trait classes can only declare abstract methods", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Trait method cannot have a function body", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 17;
markersToCheck.add(new MarkerToCheck("Reference to non-existent field `nonexist' in union template for type `@classesNegativeSemantic.MyUnion'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4;
......@@ -75,8 +76,9 @@ 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 += 20;
markersToCheck.add(new MarkerToCheck("A trait class should not define a finally block", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 19;
markersToCheck.add(new MarkerToCheck("Trait classes can only declare abstract methods", lineNum, IMarker.SEVERITY_ERROR));
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));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment