Commit 529aa61f authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: semantic check - abstract methods inherited from abstract parents must be...


OOP: semantic check - abstract methods inherited from abstract parents must be implemented (issue #427)
Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent fa0fa8b2
...@@ -87,6 +87,15 @@ type class @trait ClassWithAbstract3 { ...@@ -87,6 +87,15 @@ type class @trait ClassWithAbstract3 {
function @abstract f_abs(); function @abstract f_abs();
} }
type class @abstract ClassWithAbstract4 {
function @abstract f_abs1(in charstring pl_str);
function f_non_abs(in charstring pl_str) {
//dummy implementation
}
public function @abstract f_abs2();
}
type class InheritedAbstract extends ClassWithAbstract4 { }
type class SuperClass { type class SuperClass {
var integer vl_a; var integer vl_a;
......
...@@ -61,6 +61,18 @@ type class @abstract AbstractMethods { ...@@ -61,6 +61,18 @@ type class @abstract AbstractMethods {
// functions without a statement block // functions without a statement block
public function @abstract f_abs(); public function @abstract f_abs();
public function f_get_string() return universal charstring; public function f_get_string() return universal charstring;
// implemented function
function f_imp(in integer pl_x) return integer {
return pl_x;
}
}
type class InheritedAbstractMethods extends AbstractMethods {
// inherited abstract function must be implemented
public function f_abs() {
const integer cl_int := 0;
}
} }
// members, methods and constructors // members, methods and constructors
......
...@@ -23,7 +23,9 @@ import org.eclipse.titan.designer.AST.Reference; ...@@ -23,7 +23,9 @@ import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.Scope; import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.Type; import org.eclipse.titan.designer.AST.Type;
import org.eclipse.titan.designer.AST.TTCN3.IIncrementallyUpdateable; 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.Def_Type;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp; import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
import org.eclipse.titan.designer.parsers.ttcn3parser.ReParseException; import org.eclipse.titan.designer.parsers.ttcn3parser.ReParseException;
import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater; import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
...@@ -38,6 +40,7 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable ...@@ -38,6 +40,7 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable
private final String DUPLICATECOMPONENTREFERENCEFIRST = "Duplicate reference to class `{0}'' was first declared here"; private final String DUPLICATECOMPONENTREFERENCEFIRST = "Duplicate reference to class `{0}'' was first declared here";
private final String DUPLICATECOMPONENTREFERENCEREPEATED = "Duplicate reference to class `{0}'' was declared here again"; 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 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 Class_Type parentClass; private Class_Type parentClass;
...@@ -114,6 +117,7 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable ...@@ -114,6 +117,7 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable
} }
} }
} }
checkAbstractOverride(timestamp, extClass, parentClass);
} }
} }
} }
...@@ -128,6 +132,32 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable ...@@ -128,6 +132,32 @@ public final class ClassTypeReferenceList extends ASTNode implements ILocateable
lastCompilationTimeStamp = timestamp; lastCompilationTimeStamp = timestamp;
} }
/**
* Ensures that abstract methods inherited from abstract parent classes are implemented
* @param timestamp
* @param extClass
* @param parentClass
*/
private void checkAbstractOverride(CompilationTimeStamp timestamp, Class_Type extClass, Class_Type parentClass) {
if (parentClass.isAbstract() || parentClass.isTrait()) {
return;
}
if (extClass.isAbstract()) {
for (Definition def : extClass.getClassBody().getDefinitions()) {
if (def instanceof Def_Function) {
final Def_Function funcDef = (Def_Function)def;
if (funcDef.isAbstract()) {
if (! parentClass.getClassBody().hasAssignmentWithId(timestamp, funcDef.getIdentifier())) {
parentClass.getLocation().reportSemanticError(
MessageFormat.format(ABSTRACTMETHODUNIMPLEMENTED, funcDef.getIdentifier().getName(),
extClass.getFullName()));
}
}
}
}
}
}
/** /**
* Checks the uniqueness of the extensions, and also builds a hashmap of * Checks the uniqueness of the extensions, and also builds a hashmap of
* them to speed up further searches. * them to speed up further searches.
......
...@@ -105,7 +105,7 @@ public class OOP_Semantic_tests { ...@@ -105,7 +105,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() { private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn //oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(59); ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(61);
int lineNum = 28; int lineNum = 28;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10; lineNum += 10;
...@@ -143,7 +143,10 @@ public class OOP_Semantic_tests { ...@@ -143,7 +143,10 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("Abstract function can only be declared in an abstract or trait class", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Abstract function can only be declared in an abstract or trait class", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4; lineNum += 4;
markersToCheck.add(new MarkerToCheck("Abstract function can only be declared in an abstract or trait class", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Abstract function can only be declared in an abstract or trait class", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 19; lineNum += 15;
markersToCheck.add(new MarkerToCheck("Class must implement abstract method `f__abs1' inherited from class `@classesNegativeSemantic.ClassWithAbstract4'", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Class must implement abstract method `f__abs2' inherited from class `@classesNegativeSemantic.ClassWithAbstract4'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 13;
markersToCheck.add(new MarkerToCheck("Reference to non-existent field `nonexist' in union template for type `@classesNegativeSemantic.MyUnion'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Reference to non-existent field `nonexist' in union template for type `@classesNegativeSemantic.MyUnion'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 4; lineNum += 4;
markersToCheck.add(new MarkerToCheck("Local Definiton `vl_b' collides with definition inherited from class type `@classesNegativeSemantic.SubClass'", lineNum, IMarker.SEVERITY_ERROR)); markersToCheck.add(new MarkerToCheck("Local Definiton `vl_b' collides with definition inherited from class type `@classesNegativeSemantic.SubClass'", 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