Commit 1b2748e8 authored by Miklos Magyari's avatar Miklos Magyari Committed by Adam Knapp
Browse files

OOP: support for auto properties; property initial value (issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent e3e0e82f
......@@ -364,21 +364,27 @@ function f_invalid_value() {
var integer vl_x := value;
}
// class with property
// class with properties
type class PropertyClass {
private var integer size_;
private var charstring sizename_;
var integer @property size {
@get => size_;
@set {
size_ := value;
size_ := value;
sizename_ := value;
}
}
var integer @property nosetter {
@get => size;
}
var charstring @property nosetter_init := "abc" {
@get {
sizename_ := "xyz";
}
}
}
testcase tc_basicSyntax() runs on CT {
......
......@@ -28,6 +28,7 @@ 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.templates.ITTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.templates.TTCN3Template;
import org.eclipse.titan.designer.compiler.JavaGenData;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
......@@ -38,38 +39,67 @@ 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";
/** type of the property */
private Type myType;
/** statement block of the property getter, if defined */
private StatementBlock getStatementBlock;
/** statement block of the property setter, if defined */
private StatementBlock setStatementBlock;
/** template definition of the property getter, if defined */
private TTCN3Template getTemplate;
/** template definition of the property setter, if defined */
private TTCN3Template setTemplate;
/** a template containing the initial value for the property */
private TTCN3Template initValTemplate;
/** a fake formal param list with one member to support the 'value' keyword */
private FormalParameterList fpList;
private boolean hasGetter;
private boolean hasSetter;
private boolean isAutoProperty;
public Property_Type(Type type) {
this.myType = type;
this.setStatementBlock = null;
this.getStatementBlock = null;
this.setTemplate = null;
this.getTemplate = null;
this.initValTemplate = null;
this.isAutoProperty = true;
this.hasSetter = false;
this.hasGetter = false;
}
/**
* Sets the statement block for the property getter
* @param sb
*/
public void setStatementBlockGetter(StatementBlock sb) {
public void setStatementBlockGetter(StatementBlock sb, TTCN3Template template) {
hasGetter = true;
getStatementBlock = sb;
if (getStatementBlock != null) {
getStatementBlock.setOwnerIsProperty();
getStatementBlock.setFullNameParent(this);
}
getTemplate = template;
isAutoProperty = false;
}
/**
* Sets the statement block for the property setter
* @param sb
*/
public void setStatementBlockSetter(StatementBlock sb) {
public void setStatementBlockSetter(StatementBlock sb, TTCN3Template template) {
hasSetter = true;
setStatementBlock = sb;
if (setStatementBlock != null) {
......@@ -77,11 +107,20 @@ public final class Property_Type extends Type {
setStatementBlock.setOwnerIsProperty();
setStatementBlock.setFullNameParent(this);
}
setTemplate = template;
isAutoProperty = false;
}
@Override
/** {@inheritDoc} */
public void check(final CompilationTimeStamp timestamp) {
if (lastTimeChecked != null && !lastTimeChecked.isLess(timestamp)) {
return;
}
lastTimeChecked = timestamp;
FormalParameter valueParam = new FormalParameter(null, Assignment_type.A_PAR_VAL_IN, myType, new Identifier(Identifier_type.ID_TTCN, "value"), null, null);
List<FormalParameter> paramList = new ArrayList<FormalParameter>();
paramList.add(valueParam);
......@@ -94,6 +133,10 @@ public final class Property_Type extends Type {
setStatementBlock.setValueParamList(fpList);
setStatementBlock.check(timestamp);
}
if (initValTemplate != null && hasSetter() == false) {
initValTemplate.getLocation().reportSemanticError(INITIALVALUEWITHOUTSETTER);
initValTemplate.setIsErroneous(true);
}
}
@Override
......@@ -127,13 +170,28 @@ public final class Property_Type extends Type {
* @return
*/
public boolean hasSetter() {
if (isAutoProperty) {
return true;
}
return hasSetter;
}
/** Checks whether the property has a getter definition
* @return
*/
public boolean hasGetter() {
if (isAutoProperty) {
return true;
}
return hasGetter;
}
public void setInitValTemplate(TTCN3Template template) {
initValTemplate = template;
}
@Override
public String getOutlineIcon() {
// TODO Auto-generated method stub
......
......@@ -4545,14 +4545,26 @@ pr_SingleVarInstance[Type type, parameterEvaluationType eval] returns[Def_Var de
ArrayDimensions dimensions = null;
boolean isProperty = false;
Property_Type prop = null;
TTCN3Template initValTemplate = null;
}:
( ( prop = pr_PropertyKeyword { isProperty = true; } )?
i = pr_Identifier
( d = pr_ArrayDef { dimensions = $d.dimensions; })?
( pr_AssignmentChar
v = pr_VarInitialValue { value = $v.value; }
)?
( body = pr_PropertyBody[type] { prop = $body.prop; } )?
( ( i = pr_Identifier
( d = pr_ArrayDef { dimensions = $d.dimensions; })?
( pr_AssignmentChar
v = pr_VarInitialValue { value = $v.value; }
)?
|
prop = pr_PropertyKeyword { isProperty = true; }
i = pr_Identifier
( d = pr_ArrayDef { dimensions = $d.dimensions; })?
(
pr_AssignmentChar
templ = pr_TemplateBody {
initValTemplate = $templ.template;
initValTemplate.setLocation(getLocation( $templ.start, $templ.stop ));
}
)?
( body = pr_PropertyBody[type] { prop = $body.prop; } )?
)
)
{
if ($i.identifier != null) {
......@@ -4564,6 +4576,9 @@ pr_SingleVarInstance[Type type, parameterEvaluationType eval] returns[Def_Var de
}
}
if (isProperty) {
if (prop != null) {
prop.setInitValTemplate(initValTemplate);
}
type2 = prop == null ? new Property_Type(type) : prop;
type2.setLocation(getLocation( $prop.start, getLastVisibleToken()));
}
......@@ -9424,15 +9439,15 @@ pr_PropertyBody[Type type] returns[Property_Type prop]
}:
(
pr_BeginChar
( sbg1 = pr_PropertyGetter { $prop.setStatementBlockGetter( $sbg1.statementblock ); }
( sbs1 = pr_PropertySetter { $prop.setStatementBlockSetter( $sbs1.statementblock ); } )?
| sbs2 = pr_PropertySetter { $prop.setStatementBlockSetter( $sbs2.statementblock ); }
(sbg2 = pr_PropertyGetter { $prop.setStatementBlockGetter( $sbg2.statementblock ); } )?
( sbg1 = pr_PropertyGetter { $prop.setStatementBlockGetter( $sbg1.statementblock, $sbg1.template ); }
( sbs1 = pr_PropertySetter { $prop.setStatementBlockSetter( $sbs1.statementblock, $sbs1.template ); } )?
| sbs2 = pr_PropertySetter { $prop.setStatementBlockSetter( $sbs2.statementblock, $sbs2.template ); }
(sbg2 = pr_PropertyGetter { $prop.setStatementBlockGetter( $sbg2.statementblock, $sbg2.template ); } )?
)
pr_EndChar
);
pr_PropertyGetter returns[StatementBlock statementblock]:
pr_PropertyGetter returns[StatementBlock statementblock, TTCN3Template template]:
(
( PUBLIC | PRIVATE )?
( pr_AbstractModifier | pr_FinalModifier )?
......@@ -9441,14 +9456,14 @@ pr_PropertyGetter returns[StatementBlock statementblock]:
(
(
CLASSCASTING
pr_TemplateBody
templ = pr_TemplateBody { $template = $templ.template; }
| sb = pr_StatementBlock { $statementblock = $sb.statementblock; $statementblock.setLocation(getLocation($sb.start, $sb.stop)); }
)
)?
SEMICOLON?
);
pr_PropertySetter returns[StatementBlock statementblock]:
pr_PropertySetter returns[StatementBlock statementblock, TTCN3Template template]:
(
( PUBLIC | PRIVATE )?
( pr_AbstractModifier | pr_FinalModifier )?
......@@ -9456,7 +9471,7 @@ pr_PropertySetter returns[StatementBlock statementblock]:
SETKEYWORD
(
( CLASSCASTING
pr_TemplateBody
templ = pr_TemplateBody { $template = $templ.template; }
| sb = pr_StatementBlock { $statementblock = $sb.statementblock; $statementblock.setLocation(getLocation($sb.start, $sb.stop)); }
)
)?
......
......@@ -164,8 +164,8 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(85);
int lineNum = 32;
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(86);
int lineNum = 44;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
int i = 0;
......@@ -296,7 +296,9 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("Invalid `value` reference", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 11;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 16;
lineNum += 8;
markersToCheck.add(new MarkerToCheck("A property without a setter cannot have an initial value", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 14;
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