Commit 7ebca0bf authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: added support for inherited class members


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 9971a7a9
......@@ -29,4 +29,44 @@ type class BadInheritance extends MyUnion {
}
type class SuperClass {
var integer vl_a;
}
type class SubClass extends SuperClass {
var integer vl_b;
}
type class GrandSubClass extends SubClass {
var integer vl_c;
}
type class GrandSubClass2 extends SubClass {
var charstring vl_b;
}
type class BaseFunctionClass {
public function f_get_one() return integer {
return 1;
}
}
type class SubFunctionClass extends BaseFunctionClass {
private const integer m_const := 1;
public function f_get_one() return integer { // FIXME : incomplete marker
return m_const;
}
}
testcase tc_basicSyntax() runs on CT {
var GrandSubClass vl_gsc := GrandSubClass.create;
var integer vl_int1 := vl_gsc.vl_c; // correct : own class member
var integer vl_int2 := vl_gsc.vl_b; // correct : inherited from direct parent
var integer vl_int3 := vl_gsc.vl_a; // correct : inherited from upper parent
var charstring vl_int4 := vl_gsc.vl_d; // incorrect : nonexisting member
var charstring vl_int5 := vl_gsc.vl_a; // incorrect : type mismatch
}
}
\ No newline at end of file
......@@ -127,10 +127,11 @@ type class SuperBaseClass {
type class SubClass4 extends SuperBaseClass {
private const integer m_const2 := 2;
private const integer m_const3 := 2;
public function f_get_const() return integer {
public function f_get_const2() return integer {
return m_const2;
}
public function f_get_all_sum() return integer {
public function f_get_all_sum() return integer {
var integer vl_sum := 0;
const integer cl_const1 := 1;
const integer cl_const2 := 2;
......
......@@ -18,13 +18,14 @@ import java.util.Set;
import org.eclipse.titan.designer.AST.ASTVisitor;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.FieldSubReference;
import org.eclipse.titan.designer.AST.ILocateableNode;
import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.IReferenceChainElement;
import org.eclipse.titan.designer.AST.ISubReference;
import org.eclipse.titan.designer.AST.Identifier;
import org.eclipse.titan.designer.AST.Location;
import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.ReferenceChain;
import org.eclipse.titan.designer.AST.ReferenceFinder;
import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.ReferenceFinder.Hit;
......@@ -42,6 +43,16 @@ import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
* @author Miklos Magyari
* */
public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainElement, ILocateableNode, IIncrementallyUpdateable {
public static final String MEMBERNOTVISIBLE = "Member `{0}'' in class type `{1}'' is not visible in this scope";
public static final String LOCALINHERITANCECOLLISION = "Local Definiton `{0}'' collides with definition inherited from class type `{1}''";
public static final String INHERITEDLOCATION = "Inherited definition of `{0}'' is here";
public static final String INHERITANCECOLLISION =
"Definition `{0}'' inherited from class type `{1}'' collides with definition inherited from `{2}''";
public static final String INHERITEDDEFINITIONLOCATION = "Definition `{0}'' inherited from class type `{1}'' is here";
public static final String HIDINGSCOPEELEMENT = "The name of the inherited definition `{0}'' is not unique in the scope hierarchy";
public static final String HIDDENSCOPEELEMENT = "Previous definition with identifier `{0}'' in higher scope unit is here";
public static final String HIDINGMODULEIDENTIFIER = "Inherited definition with name `{0}'' hides a module identifier";
private final Identifier identifier;
/** The class's own definitions */
private final DefinitionContainer definitions = new DefinitionContainer();
......@@ -135,10 +146,22 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
int nrSub = reference.getSubreferences().size();
if (nrSub > 1) {
Identifier identifier = reference.getSubreferences(nrSub - 1, nrSub - 1).get(0).getId();
Definition definition = definitions.getDefinition(identifier.getName());
String name = identifier.getName();
Definition definition = definitions.getDefinition(name);
if (definition != null) {
return definition;
}
definition = extendsGainedDefinitions.get(name);
if (definition != null) {
if (VisibilityModifier.Public.equals(definition.getVisibilityModifier())) {
return definition;
}
reference.getLocation().reportSemanticError(MessageFormat.format(
MEMBERNOTVISIBLE, reference.getId().getDisplayName(), identifier.getDisplayName()));
return null;
}
}
return getParentScope().getAssBySRef(timestamp, reference);
......@@ -183,7 +206,61 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
}
final List<ClassTypeBody> bodies = getExtendsInheritedClassBodies();
int i = 0;
for (final ClassTypeBody body : bodies) {
final Map<String, Definition> subDefinitionMap = body.getDefinitionMap();
for (final Definition definition : subDefinitionMap.values()) {
final String name = definition.getIdentifier().getName();
if (definitions.hasDefinition(name)) {
final Definition localDefinition = definitions.getDefinition(name);
localDefinition.getIdentifier().getLocation().reportSemanticError(MessageFormat.format(
LOCALINHERITANCECOLLISION, definition.getIdentifier().getDisplayName(), definition.getMyScope().getFullName()));
} else if (extendsGainedDefinitions.containsKey(name)) {
final Definition previousDefinition = extendsGainedDefinitions.get(name);
if (!previousDefinition.equals(definition)) {
// it is not the same definition inherited on two paths
if (this.equals(previousDefinition.getMyScope())) {
previousDefinition.getLocation().reportSemanticError(MessageFormat.format(LOCALINHERITANCECOLLISION,
previousDefinition.getIdentifier().getDisplayName(), definition.getMyScope().getFullName()));
definition.getIdentifier().getLocation().reportSemanticWarning(
MessageFormat.format(INHERITEDLOCATION, definition.getIdentifier().getDisplayName()));
} else if (identifier != null && identifier.getLocation() != null) {
identifier.getLocation().reportSemanticError(MessageFormat.format(INHERITANCECOLLISION,
definition.getIdentifier().getDisplayName(), definition.getMyScope().getFullName(), previousDefinition.getMyScope().getFullName()));
definition.getIdentifier().getLocation().reportSingularSemanticWarning(MessageFormat.format(INHERITEDDEFINITIONLOCATION,
definition.getIdentifier().getDisplayName(), definition.getMyScope().getFullName()));
previousDefinition.getIdentifier().getLocation().reportSingularSemanticWarning(MessageFormat.format(INHERITEDDEFINITIONLOCATION,
previousDefinition.getIdentifier().getDisplayName(), previousDefinition.getMyScope().getFullName()));
}
}
} else {
extendsGainedDefinitions.put(name, definition);
if (!definition.getMyScope().getModuleScope().equals(parentScope.getModuleScope())) {
if (parentScope.hasAssignmentWithId(timestamp, definition.getIdentifier())) {
if (identifier != null && identifier.getLocation() != null) {
identifier.getLocation().reportSemanticError(
MessageFormat.format(HIDINGSCOPEELEMENT, definition.getIdentifier().getDisplayName()));
final List<ISubReference> subReferences = new ArrayList<ISubReference>();
subReferences.add(new FieldSubReference(definition.getIdentifier()));
final Reference reference = new Reference(null, subReferences);
final Assignment assignment = parentScope.getAssBySRef(timestamp, reference);
if (assignment != null && assignment.getLocation() != null) {
assignment.getLocation().reportSingularSemanticError(
MessageFormat.format(HIDDENSCOPEELEMENT, definition.getIdentifier().getDisplayName()));
}
definition.getIdentifier().getLocation().reportSingularSemanticWarning(
MessageFormat.format(INHERITEDDEFINITIONLOCATION, definition.getIdentifier().getDisplayName(),
definition.getMyScope().getFullName()));
}
} else if (parentScope.isValidModuleId(definition.getIdentifier())) {
definition.getLocation().reportSingularSemanticWarning(
MessageFormat.format(HIDINGMODULEIDENTIFIER, definition.getIdentifier().getDisplayName()));
}
}
}
}
}
}
/**
......@@ -224,6 +301,10 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
return identifier;
}
public Map<String, Definition> getDefinitionMap() {
return definitions.getDefinitionMap();
}
@Override
public boolean accept(ASTVisitor v) {
// TODO Auto-generated method stub
......
......@@ -19,14 +19,11 @@ import java.util.List;
import org.eclipse.titan.designer.AST.ArraySubReference;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.FieldSubReference;
import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.ISubReference;
import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.ITypeWithComponents;
import org.eclipse.titan.designer.AST.Identifier;
import org.eclipse.titan.designer.AST.Identifier.Identifier_type;
import org.eclipse.titan.designer.AST.ParameterisedSubReference;
import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.Type;
......
......@@ -41,9 +41,16 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(1);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(5);
int lineNum = 28;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 17;
markersToCheck.add(new MarkerToCheck("Local Definiton `vl_b' collides with definition inherited from class type `@classesNegativeSemantic.SubClass'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 11;
markersToCheck.add(new MarkerToCheck("Local Definiton `f_get_one' collides with definition inherited from class type `'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 12;
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));
return markersToCheck;
}
......
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