Commit 340277e2 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: support for property modifiers (issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent d6cfee19
......@@ -407,6 +407,13 @@ type class PropertyClass {
var integer vl_int := 0;
}
}
// invalid: bad combination of modifiers
var float @property prop_modifiers {
@final @abstract @get {
return 0.1;
}
}
}
testcase tc_basicSyntax() runs on CT {
......
......@@ -8,6 +8,7 @@
package org.eclipse.titan.designer.AST.TTCN3.types;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
......@@ -17,6 +18,7 @@ import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.Identifier;
import org.eclipse.titan.designer.AST.Identifier.Identifier_type;
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.Scope;
......@@ -26,6 +28,7 @@ import org.eclipse.titan.designer.AST.TypeCompatibilityInfo.Chain;
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.definitions.VisibilityModifier;
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;
......@@ -43,6 +46,7 @@ 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";
private static final String MODIFIERFINALABSTRACT = "Property {0} cannot be both abstract and final";
/** type of the property */
private Type myType;
......@@ -73,6 +77,20 @@ public final class Property_Type extends Type {
private boolean isAutoProperty;
/** Modifiers */
private boolean isGetterAbstract;
private boolean isSetterAbstract;
private boolean isGetterFinal;
private boolean isSetterFinal;
private boolean isGetterDeterministic;
private boolean isSetterDeterministic;
private VisibilityModifier getterModifier;
private VisibilityModifier setterModifier;
private Location getterVisibilityLocation;
private Location setterVisibilityLocation;
private Location getterModifierLocation;
private Location setterModifierLocation;
public Property_Type(Type type) {
this.myType = type;
......@@ -91,9 +109,18 @@ public final class Property_Type extends Type {
* Sets the statement block for the property getter
* @param sb
*/
public void setStatementBlockGetter(StatementBlock sb, TTCN3Template template) {
public void setStatementBlockGetter(StatementBlock sb, TTCN3Template template, VisibilityModifier modifier,
boolean isAbstract, boolean isFinal, boolean isDeterministic,
Location visibilityLocation, Location modifierLocation) {
hasGetter = true;
getStatementBlock = sb;
getterModifier = modifier;
isGetterAbstract = isAbstract;
isGetterFinal = isFinal;
isGetterDeterministic = isDeterministic;
getterVisibilityLocation = visibilityLocation;
getterModifierLocation = modifierLocation;
if (getStatementBlock != null) {
getStatementBlock.setIsGetter();
getStatementBlock.setOwnerIsProperty();
......@@ -106,9 +133,17 @@ public final class Property_Type extends Type {
* Sets the statement block for the property setter
* @param sb
*/
public void setStatementBlockSetter(StatementBlock sb, TTCN3Template template) {
public void setStatementBlockSetter(StatementBlock sb, TTCN3Template template, VisibilityModifier modifier,
boolean isAbstract, boolean isFinal, boolean isDeterministic,
Location visibilityLocation, Location modifierLocation) {
hasSetter = true;
setStatementBlock = sb;
isSetterAbstract = isAbstract;
isSetterFinal = isFinal;
isSetterDeterministic = isDeterministic;
setterVisibilityLocation = visibilityLocation;
setterModifierLocation = modifierLocation;
if (setStatementBlock != null) {
setStatementBlock.setIsSetter();
setStatementBlock.setOwnerIsProperty();
......@@ -135,6 +170,8 @@ public final class Property_Type extends Type {
paramList.add(valueParam);
fpList = new FormalParameterList(paramList);
checkModifiers();
if (getStatementBlock != null) {
getStatementBlock.check(timestamp);
if (getStatementBlock.hasReturn(timestamp) == ReturnStatus_type.RS_NO) {
......@@ -151,6 +188,20 @@ public final class Property_Type extends Type {
}
}
/**
* Semantic check of property getter/setter modifiers
*/
public void checkModifiers() {
if (isGetterAbstract && isGetterFinal) {
getterModifierLocation.reportSemanticError(MessageFormat.format(
MODIFIERFINALABSTRACT, "getter"));
}
if (isSetterAbstract && isSetterFinal) {
setterModifierLocation.reportSemanticError(MessageFormat.format(
MODIFIERFINALABSTRACT, "setter"));
}
}
@Override
public Type_type getTypetype() {
return Type_type.TYPE_PROPERTY;
......
......@@ -9462,10 +9462,26 @@ pr_PropertyBody[Type type] returns[Property_Type prop]
(
pr_BeginChar
(
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 ); } )?
sbg1 = pr_PropertyGetter {
$prop.setStatementBlockGetter( $sbg1.statementblock, $sbg1.template, $sbg1.visibility,
$sbg1.isAbstract, $sbg1.isFinal, $sbg1.isDeterministic,
$sbg1.visibilityLocation, $sbg1.modifierLocation );
}
( sbs1 = pr_PropertySetter {
$prop.setStatementBlockSetter( $sbs1.statementblock, $sbs1.template, $sbs1.visibility,
$sbs1.isAbstract, $sbs1.isFinal, $sbs1.isDeterministic,
$sbs1.visibilityLocation, $sbs1.modifierLocation );
} )?
| sbs2 = pr_PropertySetter {
$prop.setStatementBlockSetter( $sbs2.statementblock, $sbs2.template, $sbs2.visibility,
$sbs2.isAbstract, $sbs2.isFinal, $sbs2.isDeterministic,
$sbs2.visibilityLocation, $sbs2.modifierLocation );
}
(sbg2 = pr_PropertyGetter {
$prop.setStatementBlockGetter( $sbg2.statementblock, $sbg2.template, $sbg2.visibility,
$sbg2.isAbstract, $sbg2.isFinal, $sbg2.isDeterministic,
$sbg2.visibilityLocation, $sbg2.modifierLocation );
} )?
)?
pr_EndChar
{
......@@ -9475,11 +9491,19 @@ pr_PropertyBody[Type type] returns[Property_Type prop]
)?
);
pr_PropertyGetter returns[StatementBlock statementblock, TTCN3Template template]:
pr_PropertyGetter
returns[StatementBlock statementblock, TTCN3Template template, VisibilityModifier visibility,
boolean isAbstract, boolean isFinal, boolean isDeterministic,
Location visibilityLocation, Location modifierLocation]:
(
( PUBLIC | PRIVATE )?
( pr_AbstractModifier | pr_FinalModifier )?
DETERMINISTICKEYWORD?
modif = pr_PropertyModifiers {
$visibility = $modif.visibility;
$visibilityLocation = $modif.visibilityLocation;
$isAbstract = $modif.isAbstract;
$isFinal = $modif.isFinal;
$isDeterministic = $modif.isDeterministic;
$modifierLocation = $modif.modifierLocation;
}
GETKEYWORD
(
(
......@@ -9491,11 +9515,19 @@ pr_PropertyGetter returns[StatementBlock statementblock, TTCN3Template template]
SEMICOLON?
);
pr_PropertySetter returns[StatementBlock statementblock, TTCN3Template template]:
pr_PropertySetter
returns[StatementBlock statementblock, TTCN3Template template, VisibilityModifier visibility,
boolean isAbstract, boolean isFinal, boolean isDeterministic,
Location visibilityLocation, Location modifierLocation]:
(
( PUBLIC | PRIVATE )?
( pr_AbstractModifier | pr_FinalModifier )?
DETERMINISTICKEYWORD?
modif = pr_PropertyModifiers {
$visibility = $modif.visibility;
$visibilityLocation = $modif.visibilityLocation;
$isAbstract = $modif.isAbstract;
$isFinal = $modif.isFinal;
$isDeterministic = $modif.isDeterministic;
$modifierLocation = $modif.modifierLocation;
}
SETKEYWORD
(
( CLASSCASTING
......@@ -9506,6 +9538,55 @@ pr_PropertySetter returns[StatementBlock statementblock, TTCN3Template template]
SEMICOLON?
);
pr_PropertyModifiers returns[boolean isAbstract, boolean isFinal, boolean isDeterministic, VisibilityModifier visibility, Location visibilityLocation, Location modifierLocation]
@init {
$visibility = VisibilityModifier.Protected;
$isAbstract = false;
$isFinal = false;
$isDeterministic = false;
$visibilityLocation = null;
$modifierLocation = null;
}:
(
(
vis = pr_PropertyVisibility {
$visibility = $vis.visibility;
$visibilityLocation = getLocation( $vis.start, $vis.stop );
}
)
(
modif = pr_PropertyModifier {
$isAbstract = $modif.isAbstract;
$isFinal = $modif.isFinal;
$isDeterministic = $modif.isDeterministic;
$modifierLocation = getLocation( $modif.start, $modif.stop );
}
)
);
pr_PropertyVisibility returns[VisibilityModifier visibility]
@init {
$visibility = VisibilityModifier.Protected;
}:
(
PUBLIC { $visibility = VisibilityModifier.Public; }
| PRIVATE { $visibility = VisibilityModifier.Private; }
)?
;
pr_PropertyModifier returns[boolean isAbstract, boolean isFinal, boolean isDeterministic]
@init {
$isAbstract = false;
$isFinal = false;
$isDeterministic = false;
}:
(
pr_AbstractModifier { $isAbstract = true; }
| pr_FinalModifier { $isFinal = true;}
| DETERMINISTICKEYWORD { $isDeterministic = true; }
)*
;
pr_CatchBlock:
CATCH
pr_LParen
......
......@@ -164,7 +164,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(89);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(90);
int lineNum = 33;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
......@@ -305,6 +305,8 @@ public class OOP_Semantic_tests {
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 += 7;
markersToCheck.add(new MarkerToCheck("Property getter cannot be both abstract and final", 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));
......
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