Commit 9ab79648 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: some semantic checks for class casting (issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 0f066cca
...@@ -6,7 +6,6 @@ import org.eclipse.titan.designer.compiler.JavaGenData; ...@@ -6,7 +6,6 @@ import org.eclipse.titan.designer.compiler.JavaGenData;
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;
import org.eclipse.titan.designer.AST.TTCN3.statements.Statement.Statement_type;
import org.eclipse.titan.designer.AST.TTCN3.templates.TemplateInstance; import org.eclipse.titan.designer.AST.TTCN3.templates.TemplateInstance;
/** /**
......
...@@ -69,8 +69,9 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl ...@@ -69,8 +69,9 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
/** The class's own definitions */ /** The class's own definitions */
private final DefinitionContainer definitions = new DefinitionContainer(); private final DefinitionContainer definitions = new DefinitionContainer();
/** component references from the extends part or null if none */ /** class references from the extends part or null if none */
private final ClassTypeReferenceList extendsReferences; private final ClassTypeReferenceList extendsReferences;
/** /**
* The list of definitions gained through extends references. * The list of definitions gained through extends references.
**/ **/
...@@ -87,9 +88,10 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl ...@@ -87,9 +88,10 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
public ClassTypeBody(final Identifier identifier, final ClassTypeReferenceList extendsReferences) { public ClassTypeBody(final Identifier identifier, final ClassTypeReferenceList extendsReferences) {
this.identifier = identifier; this.identifier = identifier;
this.extendsReferences = extendsReferences; this.extendsReferences = extendsReferences;
if (extendsReferences != null) { if (extendsReferences != null) {
extendsReferences.setFullNameParent(this); extendsReferences.setFullNameParent(this);
} }
} }
...@@ -329,7 +331,7 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl ...@@ -329,7 +331,7 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
* *
* @return the collected class type bodies. * @return the collected class type bodies.
* */ * */
private List<ClassTypeBody> getExtendsInheritedClassBodies() { public List<ClassTypeBody> getExtendsInheritedClassBodies() {
final List<ClassTypeBody> result = new ArrayList<ClassTypeBody>(); final List<ClassTypeBody> result = new ArrayList<ClassTypeBody>();
final LinkedList<ClassTypeBody> toBeChecked = new LinkedList<ClassTypeBody>(extendsReferences.getClassBodies()); final LinkedList<ClassTypeBody> toBeChecked = new LinkedList<ClassTypeBody>(extendsReferences.getClassBodies());
while(!toBeChecked.isEmpty()) { while(!toBeChecked.isEmpty()) {
......
...@@ -37,7 +37,6 @@ import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function; ...@@ -37,7 +37,6 @@ 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.Definition;
import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameter; 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.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.definitions.VisibilityModifier;
import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock; import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock;
import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template; import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template;
...@@ -391,4 +390,24 @@ public final class Class_Type extends Type implements ITypeWithComponents { ...@@ -391,4 +390,24 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return null; return null;
} }
/** Check whether a class is a direct or indirect superclass/subclass of this class
*
* @param class to be checked
* @return
*/
public boolean isRelatedClass(Class_Type related) {
List<ClassTypeBody> bodies = getClassBody().getExtendsInheritedClassBodies();
for (ClassTypeBody body : bodies) {
if (body.getMyType() == related) {
return true;
}
}
List<ClassTypeBody> relatedBodies = related.getClassBody().getExtendsInheritedClassBodies();
for (ClassTypeBody body : relatedBodies) {
if (body.getMyType() == this) {
return true;
}
}
return false;
}
} }
\ No newline at end of file
...@@ -3,19 +3,28 @@ package org.eclipse.titan.designer.AST.TTCN3.values.expressions; ...@@ -3,19 +3,28 @@ package org.eclipse.titan.designer.AST.TTCN3.values.expressions;
import org.eclipse.titan.designer.AST.ASTVisitor; import org.eclipse.titan.designer.AST.ASTVisitor;
import org.eclipse.titan.designer.AST.Assignment; import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.IReferenceChain; import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.IType.Type_type; import org.eclipse.titan.designer.AST.IType.Type_type;
import org.eclipse.titan.designer.AST.IValue; import org.eclipse.titan.designer.AST.IValue;
import org.eclipse.titan.designer.AST.Reference; 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.Expected_Value_type; import org.eclipse.titan.designer.AST.TTCN3.Expected_Value_type;
import org.eclipse.titan.designer.AST.TTCN3.types.Class_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Referenced_Type;
import org.eclipse.titan.designer.AST.TTCN3.values.Expression_Value; import org.eclipse.titan.designer.AST.TTCN3.values.Expression_Value;
import org.eclipse.titan.designer.AST.TTCN3.values.Expression_Value.Operation_type;
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;
/** Represents TTCN3 class casting excpressions (OOP extension)
*
* @author Miklos Magyari
*
*/
public class ClassCastingExpression extends Expression_Value { public class ClassCastingExpression extends Expression_Value {
private static final String CASTINGTOUNRELATED = "A class can only be cast to a superclass or subclass";
private final Reference left; private final Reference left;
private final Type right; private final Type right;
...@@ -61,7 +70,31 @@ public class ClassCastingExpression extends Expression_Value { ...@@ -61,7 +70,31 @@ public class ClassCastingExpression extends Expression_Value {
return lastValue; return lastValue;
} }
Assignment ass = left.getRefdAssignment(timestamp, isErroneous); Class_Type leftClass = null;
Class_Type rightClass = null;
final Assignment assignment = left.getRefdAssignment(timestamp, isErroneous);
if (assignment == null) {
return null;
}
final IType refdType = assignment.getType(timestamp);
if (refdType instanceof Referenced_Type) {
final IType refd = ((Referenced_Type)refdType).getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
leftClass = (Class_Type)refd;
}
}
if (right instanceof Referenced_Type) {
final IType refd = ((Referenced_Type)right).getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
rightClass = (Class_Type)refd;
}
}
if (leftClass != null && rightClass != null) {
if (leftClass.isRelatedClass(rightClass) == false) {
getLocation().reportSemanticError(CASTINGTOUNRELATED);
}
}
return null; return null;
} }
......
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