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

OOP: semantic check - return statement for properties (issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 18b8ae96
......@@ -233,7 +233,7 @@ type class FinallyClass3 {
} finally {
return;
}
// bad combination of class modifiers
type class @final @abstract BadClass1 { }
type class @final @trait BadClass3 { }
......@@ -385,7 +385,7 @@ type class PropertyClass {
// invalid: a property without a setter cannot be initialized
var charstring @property nosetter_init := "abc" {
@get {
sizename_ := "xyz";
return "xyz";
}
}
......@@ -393,6 +393,20 @@ type class PropertyClass {
var float @property emptybody {
}
// invalid: setter properties cannot have a return statement
var charstring @property setter_with_return {
@set {
return "bad";
}
}
// invalid: getter without a return statement
var integer @property getter_without_return {
@get {
var integer vl_int := 0;
}
}
}
testcase tc_basicSyntax() runs on CT {
......
......@@ -338,6 +338,12 @@ type class CorrectWithProperty {
var float @property getPi {
@get => piVal;
}
var float @property getPi2 {
@get {
return piVal;
}
}
}
testcase tc_basicSyntax() runs on CT {
......
......@@ -27,6 +27,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.templates.ITTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.templates.TTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.types.Property_Type;
import org.eclipse.titan.designer.AST.TTCN3.values.expressions.ExpressionStruct;
import org.eclipse.titan.designer.compiler.JavaGenData;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
......@@ -36,6 +37,7 @@ import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
/**
* @author Kristof Szabados
* @author Miklos Magyari
* */
public final class Return_Statement extends Statement {
private static final String SPECIFICVALUEEXPECTED = "A specific value without matching symbols was expected as return value";
......@@ -44,8 +46,9 @@ public final class Return_Statement extends Statement {
private static final String UNEXPECTEDRETURNVALUE = "Unexpected return value. The function does not have return type";
private static final String UNEXPETEDRETURNSTATEMENT = "Return statement cannot be used in a {0}. It is allowed only in functions and altsteps";
private static final String ALTSTEPRETURNINGVALUE = "An altstep cannot return a value";
private static final String USAGEINCONTROLPART = "Return statement cannot be used in the control part. It is alowed only in functions and altsteps";
private static final String USAGEINCONTROLPART = "Return statement cannot be used in the control part. It is allowed only in functions and altsteps";
private static final String RETURNINDESTRUCTOR = "Return statement cannot be used in a class destructor";
private static final String INVALIDSETTERRETURN = "Return statement cannot be used in a property setter";
private static final String FULLNAMEPART = ".returnexpression";
private static final String STATEMENT_NAME = "return";
......@@ -123,6 +126,23 @@ public final class Return_Statement extends Statement {
return;
}
if (definition == null) {
if (getMyScope() instanceof StatementBlock) {
final StatementBlock block = (StatementBlock)getMyScope();
if (block.ownerIsProperty() == true) {
if (block.isPropertyGetter()) {
final INamedNode node = block.getNameParent();
if (node instanceof Property_Type) {
final Property_Type property = (Property_Type)node;
// TODO check return type if it matches the property type
return;
}
}
if (block.isPropertySetter()) {
location.reportSemanticError(INVALIDSETTERRETURN);
return;
}
}
}
location.reportSemanticError(USAGEINCONTROLPART);
return;
}
......
......@@ -130,6 +130,9 @@ public final class StatementBlock extends TTCN3Scope implements ILocateableNode,
/** Indicates if it is a statement block of a property setter */
private boolean isPropertySetter;
/** Indicates if it is a statement block of a property getter */
private boolean isPropertyGetter;
/** Formal parameter list with only one member.
* It is used to support the special 'value' keyword in class properties
*/
......@@ -1164,6 +1167,28 @@ public final class StatementBlock extends TTCN3Scope implements ILocateableNode,
return false;
}
/**
* Checks wheter a statement block belongs to a property getter
* @return
*/
public boolean isPropertyGetter() {
if (ownerIsProperty) {
return this.isPropertyGetter;
}
return false;
}
/**
* Sets the flag to indicate it is a statement block of a property getter
*/
public void setIsGetter() {
this.isPropertyGetter = true;
}
/**
* Sets the flag to indicate it is a statement block of a property setter
*/
public void setIsSetter() {
this.isPropertySetter = true;
}
......
......@@ -27,6 +27,7 @@ import org.eclipse.titan.designer.AST.TTCN3.Expected_Value_type;
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.statements.StatementBlock;
import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock.ReturnStatus_type;
import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.templates.TTCN3Template;
import org.eclipse.titan.designer.compiler.JavaGenData;
......@@ -41,7 +42,7 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
public final class Property_Type extends Type {
private static final String INITIALVALUEWITHOUTSETTER = "A property without a setter cannot have an initial value";
private static final String EMPTYBODY = "An empty property body is not allowed";
private static final String GETMISSINGRETURN = "Statement block of a property getter should have a `return' statement";
/** type of the property */
private Type myType;
......@@ -94,6 +95,7 @@ public final class Property_Type extends Type {
hasGetter = true;
getStatementBlock = sb;
if (getStatementBlock != null) {
getStatementBlock.setIsGetter();
getStatementBlock.setOwnerIsProperty();
getStatementBlock.setFullNameParent(this);
}
......@@ -135,6 +137,9 @@ public final class Property_Type extends Type {
if (getStatementBlock != null) {
getStatementBlock.check(timestamp);
if (getStatementBlock.hasReturn(timestamp) == ReturnStatus_type.RS_NO) {
getStatementBlock.getLocation().reportSemanticError(GETMISSINGRETURN);
}
}
if (setStatementBlock != null) {
setStatementBlock.setValueParamList(fpList);
......@@ -166,6 +171,7 @@ public final class Property_Type extends Type {
public void setMyScope(final Scope scope) {
super.setMyScope(scope);
if (getStatementBlock != null) {
Scope s = getMyScope();
getStatementBlock.setMyScope(scope);
}
if (setStatementBlock != null) {
......
......@@ -4941,7 +4941,7 @@ public class AST_tests {
markersToCheck.add(new MarkerToCheck("Too few parameters: 1 was expected instead of 0", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 1;
for (i = 0; i < 2; i++) {
markersToCheck.add(new MarkerToCheck("Return statement cannot be used in the control part. It is alowed only in functions and altsteps", lineNum++, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Return statement cannot be used in the control part. It is allowed only in functions and altsteps", lineNum++, IMarker.SEVERITY_ERROR));
}
 
return markersToCheck;
......@@ -164,7 +164,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(87);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(89);
int lineNum = 33;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
......@@ -301,7 +301,11 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("A property without a setter cannot have an initial value", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 7;
markersToCheck.add(new MarkerToCheck("An empty property body is not allowed", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 12;
lineNum += 7;
markersToCheck.add(new MarkerToCheck("Return statement cannot be used in a property setter", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 6;
markersToCheck.add(new MarkerToCheck("Statement block of a property getter should have a `return' statement", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 13;
markersToCheck.add(new MarkerToCheck("Unknown field reference", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 8;
......
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