Commit e2f49d74 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: semantic check - class 'runs on' compatibility with parent (issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 2a6c8290
......@@ -16,6 +16,10 @@ type component CT {
port PT pt_PT;
}
type component CT2 {
port PT pt2_PT;
}
type port PT message { inout integer; } with { extension "internal" }
type union MyUnion {
......@@ -51,6 +55,11 @@ type class RepeatedExtends extends MinimalClass, BaseClass, MinimalClass {
}
// runs on compatibility
type class RunsonClass1 runs on CT { }
type class RunsonClass2 extends RunsonClass1 runs on CT { }
type class RunsonClass3 extends RunsonClass1 runs on CT2 { }
// self extend
type class @trait TC {}
type class AA extends DD, TC, DD { }
......
......@@ -136,6 +136,10 @@ type class ConstructorOverrideSub {
}
}
// runs on compatibility
type class RunsonClass1 runs on CT { }
type class RunsonClass2 extends RunsonClass1 runs on CT { }
// nested classes
type class OuterClass {
private var integer m_int := 0;
......
/*****************************************************************
** @author STF 572
** @version 0.0.1
** @purpose 5.1.1.0, Ensure that The runs on type of a class shall be runs on compatible with the runs on type of the superclass.
** @verdict pass reject
**
** modified by Miklos Magyari
*****************************************************************/
module NegSem_50101_top_level_010 "TTCN-3:2018 Object-Oriented" {
type component GeneralComp {
}
type port Myport message {
inout octetstring;
}
type component MessageComp {
port Myport p1_PT;
};
public type class t_superclass_with_incompatible runs on MessageComp {
var octetstring v_o := '1100'O;
public function sending_vo() {
log(this.v_o);
}
}
public type class t_subclass extends t_superclass_with_incompatible runs on GeneralComp {
}
testcase tc_NegSem_50101_top_level_010() runs on GeneralComp {
var t_subclass vl_a := t_subclass.create(); // not allowed
if (vl_a.v_o == '1100'O) {
setverdict(pass);
} else {
setverdict(fail);
}
}
control {
execute(tc_NegSem_50101_top_level_010());
}
}
\ No newline at end of file
......@@ -26,6 +26,7 @@ import org.eclipse.titan.designer.AST.TTCN3.IIncrementallyUpdateable;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Type;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition;
import org.eclipse.titan.designer.AST.TTCN3.definitions.RunsOnScope;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
import org.eclipse.titan.designer.parsers.ttcn3parser.ReParseException;
import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
......@@ -41,8 +42,9 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable
private final String DUPLICATECOMPONENTREFERENCEREPEATED = "Duplicate reference to class `{0}'' was declared here again";
private final String CLASSCANNOTEXTENDITSELF = "A class cannot extend itself neither directly nor indirectly";
private final String ABSTRACTMETHODUNIMPLEMENTED = "Class must implement abstract method `{0}'' inherited from class `{1}''";
private final String INCOMPATIBLERUNSON = "Class `{0}'' is not 'runs on' compatible with parent `{1}''";
private Class_Type parentClass;
private Class_Type myClass;
private final List<Reference> classReferences;
private Location location;
......@@ -60,7 +62,7 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable
}
public void setParentClass(Class_Type parentClass) {
this.parentClass = parentClass;
this.myClass = parentClass;
}
public List<ClassTypeBody> getClassBodies() {
......@@ -96,33 +98,41 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable
if (refdAss instanceof Def_Type) {
final Def_Type deftype = (Def_Type)refdAss;
final Type type = deftype.getType(timestamp);
if (type instanceof Class_Type) {
if (type instanceof Class_Type) {
final Class_Type extClass = (Class_Type)type;
if (extClass == parentClass) {
final Component_Type extRunsOnType = extClass.getRunsOnType(timestamp);
final Component_Type myRunsOnType = myClass.getRunsOnType(timestamp);
if (myRunsOnType != null && !extRunsOnType.isCompatible(timestamp, myRunsOnType, null, null, null)) {
myClass.getRunsOnRef().getLocation().reportSemanticError(
MessageFormat.format(INCOMPATIBLERUNSON, myClass.getFullName(), extClass.getFullName()));
}
if (extClass == myClass) {
classRef.getLocation().reportSemanticError(CLASSCANNOTEXTENDITSELF);
}
if (extClass.isFinal()) {
classRef.getLocation().reportSemanticError(FINALCANNOTBEEXTENDED);
parentClass.setIsErroneous(true);
myClass.setIsErroneous(true);
}
if (! extClass.isTrait()) {
nrNonTraitExtends++;
if (parentClass.isTrait()) {
if (myClass.isTrait()) {
classRef.getLocation().reportSemanticError(TRAITEXTENDSTRAIT);
parentClass.setIsErroneous(true);
myClass.setIsErroneous(true);
} else {
if (nrNonTraitExtends > 1) {
classRef.getLocation().reportSemanticError(ONLYONNONTRAIT);
parentClass.setIsErroneous(true);
myClass.setIsErroneous(true);
}
}
}
checkAbstractOverride(timestamp, extClass, parentClass);
checkAbstractOverride(timestamp, extClass, myClass);
}
}
}
checkSelfReference(timestamp, parentClass);
checkSelfReference(timestamp, myClass);
checkUniqueness(timestamp);
for (final ClassTypeBody body : orderedClassTypeBodies) {
......
......@@ -37,6 +37,7 @@ import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition;
import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameter;
import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameterList;
import org.eclipse.titan.designer.AST.TTCN3.definitions.RunsOnScope;
import org.eclipse.titan.designer.AST.TTCN3.definitions.VisibilityModifier;
import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock;
import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template;
......@@ -63,19 +64,32 @@ public final class Class_Type extends Type implements ITypeWithComponents {
private final boolean isTrait;
private final Location modifierLocation;
private final StatementBlock finallyBlock;
private final Reference runsOnRef;
private final Reference mtcRef;
private final Reference systemRef;
public Class_Type(ClassTypeBody classBody, boolean isAbstract, boolean isFinal, boolean isTrait, Location modifierLocation, StatementBlock finallyBlock) {
private Component_Type runsOnType;
public Class_Type(ClassTypeBody classBody, boolean isAbstract, boolean isFinal, boolean isTrait, Location modifierLocation,
final Reference runsOnRef, final Reference mtcRef, final Reference systemRef, StatementBlock finallyBlock) {
this.classBody = classBody;
this.isAbstract = isAbstract;
this.isFinal = isFinal;
this.isTrait = isTrait;
this.modifierLocation = modifierLocation;
this.finallyBlock = finallyBlock;
this.runsOnRef = runsOnRef;
this.mtcRef = mtcRef;
this.systemRef = systemRef;
if (classBody != null) {
classBody.setFullNameParent(this);
classBody.setMyType(this);
}
if (runsOnRef != null) {
runsOnRef.setFullNameParent(this);
}
if (finallyBlock != null) {
finallyBlock.setFullNameParent(this);
finallyBlock.setOwnerIsDestructor();
......@@ -83,7 +97,7 @@ public final class Class_Type extends Type implements ITypeWithComponents {
}
public Class_Type() {
this(null, true, false, false, null, null);
this(null, true, false, false, null, null, null, null, null);
}
@Override
......@@ -114,6 +128,9 @@ public final class Class_Type extends Type implements ITypeWithComponents {
finallyBlock.setMyScope(scope);
}
}
if (runsOnRef != null) {
runsOnRef.setMyScope(scope);
}
}
@Override
......@@ -171,6 +188,10 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return classBody;
}
public Reference getRunsOnRef() {
return runsOnRef;
}
@Override
/** {@inheritDoc} */
public void check(final CompilationTimeStamp timestamp) {
......@@ -178,6 +199,11 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return;
}
runsOnType = null;
if (runsOnRef != null) {
runsOnType = runsOnRef.chkComponentypeReference(timestamp);
}
if (isAbstract && isFinal) {
modifierLocation.reportSemanticError(ABSTRACTCANNOTBEFINAL);
setIsErroneous(true);
......@@ -259,6 +285,11 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return isFinal;
}
public Component_Type getRunsOnType(final CompilationTimeStamp timestamp) {
check(timestamp);
return runsOnType;
}
@Override
public Identifier getComponentIdentifierByName(Identifier identifier) {
// TODO Auto-generated method stub
......
......@@ -9015,9 +9015,21 @@ pr_ClassTypeDef returns[Def_Type def_type]
( tm = pr_TraitModifier { isTrait = $tm.isTrait; } )?
i = pr_Identifier
ecd = pr_ExtendsClassDef { refs = $ecd.refList; }
(pr_RunsOnSpec[runsonHelper])?
(pr_MTCSpec[mtcHelper])?
(pr_SystemSpec[systemspecHelper])?
(runson = pr_RunsOnSpec[runsonHelper] {
if (runsonHelper.runsonReference != null) {
runsonHelper.runsonReference.setLocation(getLocation($runson.start, $runson.stop));
}
})?
(mtc = pr_MTCSpec[mtcHelper] {
if (mtcHelper.mtcReference != null) {
mtcHelper.mtcReference.setLocation(getLocation($mtc.start, $mtc.stop));
}
})?
(sys = pr_SystemSpec[systemspecHelper] {
if (systemspecHelper.runsonReference != null) {
systemspecHelper.runsonReference.setLocation(getLocation($sys.start, $sys.stop));
}
})?
pr_BeginChar
cml = pr_ClassMemberList[$i.identifier, refs] { body = $cml.body; }
pr_EndChar
......@@ -9030,7 +9042,7 @@ pr_ClassTypeDef returns[Def_Type def_type]
if (body == null) {
body = new ClassTypeBody($i.identifier, refs);
}
Class_Type type = new Class_Type(body, isAbstract, isFinal, isTrait, getLocation($kw.stop, $i.start), finallyBlock);
Class_Type type = new Class_Type(body, isAbstract, isFinal, isTrait, getLocation($kw.stop, $i.start), runsonHelper.runsonReference, mtcHelper.mtcReference, systemspecHelper.systemReference, finallyBlock);
type.setLocation(getLocation($start, getLastVisibleToken()));
$def_type = new Def_Type($i.identifier, type);
$def_type.setLocation(getLocation($kw.start, $i.stop));
......
......@@ -53,6 +53,9 @@ public class OOP_Semantic_tests {
Designer_plugin_tests.checkSemanticMarkersOnFile(NegSem_50101_top_level_008_ttcn_initializer(),
OOP_Syntax_tests.OOP_DIR_PATH + "negative/NegSem_50101_top_level_008.ttcn");
Designer_plugin_tests.checkSemanticMarkersOnFile(NegSem_50101_top_level_010_ttcn_initializer(),
OOP_Syntax_tests.OOP_DIR_PATH + "negative/NegSem_50101_top_level_010.ttcn");
Designer_plugin_tests.checkSemanticMarkersOnFile(NegSem_5010102_abstractClasses_001_ttcn_initializer(),
OOP_Syntax_tests.OOP_DIR_PATH + "negative/NegSem_5010102_abstractClasses_001.ttcn");
......@@ -97,6 +100,15 @@ public class OOP_Semantic_tests {
return markersToCheck;
}
private ArrayList<MarkerToCheck> NegSem_50101_top_level_010_ttcn_initializer() {
//NegSem_50101_top_level_010.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(1);
int lineNum = 30;
markersToCheck.add(new MarkerToCheck("Class `@NegSem_50101_top_level_010.t_subclass' is not runs on compatible with parent `@NegSem_50101_top_level_010.t_superclass_with_incompatible'", lineNum, IMarker.SEVERITY_ERROR));
return markersToCheck;
}
private ArrayList<MarkerToCheck> NegSem_5010102_abstractClasses_001_ttcn_initializer() {
//NegSem_5010102_abstractClasses_001.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(1);
......@@ -126,8 +138,8 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(74);
int lineNum = 28;
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(75);
int lineNum = 32;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
int i = 0;
......@@ -143,7 +155,9 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("A class can only extend one non-trait class", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Duplicate reference to class `MinimalClass' was declared here again", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Duplicate reference to class `MinimalClass' was first declared here", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 6;
lineNum += 7;
markersToCheck.add(new MarkerToCheck("Class `@classesNegativeSemantic.RunsonClass3' is not runs on compatible with parent `@classesNegativeSemantic.RunsonClass1'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4;
markersToCheck.add(new MarkerToCheck("A class cannot extend itself neither directly nor indirectly", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("A class can only extend one non-trait class", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Duplicate reference to class `DD' was declared here again", lineNum, IMarker.SEVERITY_ERROR));
......
......@@ -44,6 +44,7 @@ public class OOP_Syntax_tests {
"NegSem_50101_top_level_002.ttcn",
"NegSem_50101_top_level_007.ttcn",
"NegSem_50101_top_level_008.ttcn",
"NegSem_50101_top_level_010.ttcn",
"NegSem_5010102_abstractClasses_001.ttcn",
"NegSem_5010109_Visibility_001.ttcn",
"NegSem_5010109_Visibility_004.ttcn"
......
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