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

OOP: class casting improvements


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 728fac03
......@@ -27,6 +27,8 @@ type union MyUnion {
charstring b
};
type class Casting {}
// raise exception
function f_with_exception(integer pl_int) return integer exception(integer) {
if (pl_int > 100) {
......@@ -42,7 +44,8 @@ function f_with_exception(integer pl_int) return integer exception(integer) {
}
testcase tc_basicWarning() runs on CT {
var Casting vl_casting := Casting.create;
var object vl_obj := vl_casting => Casting; // class cast to itself
}
}
\ No newline at end of file
......@@ -90,6 +90,10 @@ public final class Class_Type extends Type implements ITypeWithComponents {
private Component_Type mtcType;
private Component_Type systemType;
public enum ClassRelation {
Identical, Related, Unrelated
}
public Class_Type(ClassTypeBody classBody, boolean isAbstract, boolean isFinal, boolean isTrait, boolean isExternal,
Location modifierLocation, final Reference runsOnRef, final Reference mtcRef, final Reference systemRef,
ClassTypeReferenceList refs, StatementBlock finallyBlock) {
......@@ -125,6 +129,9 @@ public final class Class_Type extends Type implements ITypeWithComponents {
}
}
/**
* constructor used for classes defined using the 'object' keyword
*/
public Class_Type() {
this(null, true, false, false, false, null, null, null, null, null, null);
}
......@@ -177,31 +184,35 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return this;
}
final ISubReference subreference = subreferences.get(actualSubReference);
final ISubReference subreference = subreferences.get(actualSubReference);
/* methods defined by 'object' */
if (subreference.getReferenceType() == Subreference_type.parameterisedSubReference) {
if (subreference.getId().getName().equals("toString")) {
Identifier id = new Identifier(Identifier_type.ID_NAME, "toString");
Def_Function function = new Def_Function(id, new FormalParameterList(new ArrayList<FormalParameter>()), new UniversalCharstring_Type());
function.setMyScope(reference.getMyScope());
return function.getType(timestamp);
}
if (subreference.getId().getName().equals("equals")) {
Identifier id = new Identifier(Identifier_type.ID_NAME, "equals");
Identifier objid = new Identifier(Identifier_type.ID_NAME, "obj");
List<FormalParameter> list = new ArrayList<FormalParameter>();
list.add(new FormalParameter(null, Assignment_type.A_PAR_VAL_IN,
new Anytype_Type(), objid, null, null));
FormalParameterList paramList = new FormalParameterList(list);
Def_Function function = new Def_Function(id, paramList, new Boolean_Type());
function.setMyScope(reference.getMyScope());
return function.getType(timestamp);
}
Assignment assignment = null;
if (classBody != null) {
assignment = classBody.getAssByIdentifier(timestamp, subreference.getId());
}
Assignment assignment = classBody.getAssByIdentifier(timestamp, subreference.getId());
if (assignment == null) {
/* methods defined by 'object' */
if (subreference.getReferenceType() == Subreference_type.parameterisedSubReference) {
if (subreference.getId().getName().equals("toString")) {
Identifier id = new Identifier(Identifier_type.ID_NAME, "toString");
Def_Function function = new Def_Function(id, new FormalParameterList(new ArrayList<FormalParameter>()), new UniversalCharstring_Type());
function.setMyScope(reference.getMyScope());
function.setLocation(NULL_Location.INSTANCE);
return function.getType(timestamp);
}
if (subreference.getId().getName().equals("equals")) {
Identifier id = new Identifier(Identifier_type.ID_NAME, "equals");
Identifier objid = new Identifier(Identifier_type.ID_NAME, "obj");
List<FormalParameter> list = new ArrayList<FormalParameter>();
list.add(new FormalParameter(null, Assignment_type.A_PAR_VAL_IN,
new Anytype_Type(), objid, null, null));
FormalParameterList paramList = new FormalParameterList(list);
Def_Function function = new Def_Function(id, paramList, new Boolean_Type());
function.setMyScope(reference.getMyScope());
function.setLocation(NULL_Location.INSTANCE);
return function.getType(timestamp);
}
}
subreference.getLocation().reportSemanticError(UNKNOWNFIELD);
return null;
}
......@@ -493,6 +504,15 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return isFinal;
}
/**
* returns true for classes defined with the 'object' keyword
*
* @return
*/
public boolean isObject() {
return classBody == null;
}
public Component_Type getRunsOnType(final CompilationTimeStamp timestamp) {
check(timestamp);
return runsOnType;
......@@ -528,7 +548,6 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return true;
}
@Override
public boolean generatesOwnClass(JavaGenData aData, StringBuilder source) {
// TODO Auto-generated method stub
......@@ -558,27 +577,38 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return null;
}
/** Check whether a class is a direct or indirect superclass/subclass of this class
/** Checks whether a class is a direct or indirect superclass/subclass of this class
*
* @param class to be checked
* @return
*/
public boolean isRelatedClass(CompilationTimeStamp timestamp, Class_Type related) {
public ClassRelation isRelatedClass(CompilationTimeStamp timestamp, Class_Type related) {
if (this.isObject()) {
if (related.isObject()) {
return ClassRelation.Identical;
} else {
return ClassRelation.Related;
}
}
if (this.equals(related)) {
return ClassRelation.Identical;
}
getClassBody().check(timestamp);
List<ClassTypeBody> bodies = getClassBody().getExtendsInheritedClassBodies(timestamp);
for (ClassTypeBody body : bodies) {
if (body.getMyType() == related) {
return true;
return ClassRelation.Related;
}
}
related.getClassBody().check(timestamp);
List<ClassTypeBody> relatedBodies = related.getClassBody().getExtendsInheritedClassBodies(timestamp);
for (ClassTypeBody body : relatedBodies) {
if (body.getMyType() == this) {
return true;
return ClassRelation.Related;
}
}
return false;
return ClassRelation.Unrelated;
}
private FormalParameterList getConstructorFormalParameterList() {
......
package org.eclipse.titan.designer.AST.TTCN3.values.expressions;
import java.text.MessageFormat;
import org.eclipse.titan.designer.AST.ASTVisitor;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.IReferenceChain;
......@@ -17,13 +19,15 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
import org.eclipse.titan.designer.parsers.ttcn3parser.ReParseException;
import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
/** Represents TTCN3 class casting excpressions (OOP extension)
/** Represents TTCN3 class casting expressions (OOP extension)
*
* @author Miklos Magyari
*
*/
public class ClassCastingExpression extends Expression_Value {
private static final String CASTINGTOUNRELATED = "A class can only be cast to a superclass or subclass";
private static final String UNNECESSARYCAST = "Unnecessary cast: class is cast to itself";
private static final String NOTACLASS = "`{0}'' side of class casting expression is not a class";
private final Reference left;
private final Type right;
......@@ -80,18 +84,40 @@ public class ClassCastingExpression extends Expression_Value {
if (refdType instanceof Referenced_Type) {
final IType refd = ((Referenced_Type)refdType).getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
leftClass = (Class_Type)refd;
IType ltype = ((Class_Type)refd).getFieldType(timestamp, left, 1, Expected_Value_type.EXPECTED_DYNAMIC_VALUE, false);
if (ltype instanceof Referenced_Type) {
final IType rltype = ((Referenced_Type)ltype).getTypeRefd(timestamp, referenceChain);
if (rltype instanceof Class_Type) {
leftClass = (Class_Type)rltype;
}
} else if (ltype instanceof Class_Type) {
leftClass = (Class_Type)ltype;
} else {
left.getLocation().reportSemanticError(MessageFormat.format(NOTACLASS, "left"));
}
}
} else if (refdType instanceof Class_Type) {
leftClass = (Class_Type)refdType;
}
if (right instanceof Referenced_Type) {
final IType refd = ((Referenced_Type)right).getTypeRefdLast(timestamp);
if (refd instanceof Class_Type) {
rightClass = (Class_Type)refd;
} else {
right.getLocation().reportSemanticError(MessageFormat.format(NOTACLASS, "right"));
}
} else if (right instanceof Class_Type) {
rightClass = (Class_Type)right;
}
if (leftClass != null && rightClass != null) {
if (leftClass.isRelatedClass(timestamp, rightClass) == false) {
switch (leftClass.isRelatedClass(timestamp, rightClass)) {
case Unrelated:
getLocation().reportSemanticError(CASTINGTOUNRELATED);
break;
case Identical:
getLocation().reportSemanticWarning(UNNECESSARYCAST);
break;
default:
}
}
......
......@@ -6345,7 +6345,10 @@ pr_Type returns[Type type]
$type = null;
}:
( t1 = pr_PredefinedType { $type = $t1.type; }
| OBJECTKEYWORD { $type = new Class_Type(); }
| obj = pr_ObjectKeyword {
$type = new Class_Type();
$type.setLocation(getLocation($obj.start, $obj.stop));
}
| t3 = pr_ReferencedType { $type = $t3.type; }
)
{
......@@ -9642,6 +9645,10 @@ pr_ClassTemplateDef returns[Def_Template def_template, Type type]
}
};
pr_ObjectKeyword:
OBJECTKEYWORD
;
pr_ClassCastingOp returns[ClassCastingExpression value]
@init {
Reference reference = null;
......@@ -9650,7 +9657,10 @@ pr_ClassCastingOp returns[ClassCastingExpression value]
( var = pr_VariableRef { reference = $var.reference; }
CLASSCASTING
( type = pr_ReferencedType { type = $type.type; }
| OBJECTKEYWORD
| obj = pr_ObjectKeyword {
type = new Class_Type();
type.setLocation(getLocation($obj.start, $obj.stop));
}
| LPAREN pr_VariableRef RPAREN
)
)
......
......@@ -170,9 +170,11 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopWarning_ttcn_initializer() {
//OopWarningSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(1);
int lineNum = 34;
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(2);
int lineNum = 36;
markersToCheck.add(new MarkerToCheck("Control never reaches this statement", lineNum, IMarker.SEVERITY_WARNING));
lineNum += 12;
markersToCheck.add(new MarkerToCheck("Unnecessary cast: class is cast to itself", lineNum, IMarker.SEVERITY_WARNING));
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