Commit 7b9acd94 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

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


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 6c0d58f3
......@@ -365,7 +365,7 @@ function f_invalid_value() {
}
// class with property
type class PorpertyClass {
type class PropertyClass {
private var integer size_;
private var charstring sizename_;
var integer @property size {
......@@ -375,6 +375,10 @@ type class PorpertyClass {
sizename_ := value;
}
}
var integer @property nosetter {
@get => size;
}
}
testcase tc_basicSyntax() runs on CT {
......@@ -405,6 +409,9 @@ testcase tc_basicSyntax() runs on CT {
var SubFunctionClass vl_sub := SubFunctionClass.create;
var integer vl_subint := vl_sub.m_const;
var PropertyClass vl_prop := PropertyClass.create;
vl_prop.nosetter := 10;
}
}
\ No newline at end of file
......@@ -77,7 +77,8 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
public static final String ASN1SETTINGEXPECTED = "Reference to ASN.1 setting expected";
private static final String INVALIDVALUEREFERENCE = "Invalid `value` reference";
private static final String VALUENOTSETTER = "A property getter cannot have a `value` reference";
public enum Ref_Type {
REF_BASIC,
REF_THIS,
......@@ -511,6 +512,10 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
if (valueParam != null) {
return (Assignment)valueParam;
} else {
if (sb.ownerIsProperty() && ! sb.isPropertySetter()) {
getLocation().reportSemanticError(VALUENOTSETTER);
return null;
}
getLocation().reportSemanticError(INVALIDVALUEREFERENCE);
return null;
}
......
......@@ -49,6 +49,7 @@ import org.eclipse.titan.designer.AST.TTCN3.templates.TTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.templates.ValueList_Template;
import org.eclipse.titan.designer.AST.TTCN3.types.CompField;
import org.eclipse.titan.designer.AST.TTCN3.types.ComponentTypeBody;
import org.eclipse.titan.designer.AST.TTCN3.types.Property_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.TTCN3_Sequence_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.TTCN3_Set_Type;
import org.eclipse.titan.designer.AST.TTCN3.values.Bitstring_Value;
......@@ -66,6 +67,7 @@ import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
/**
* @author Kristof Szabados
* @author Miklos Magyari
* */
public final class Assignment_Statement extends Statement {
private static final String FULLNAMEPART = ".assignment";
......@@ -78,6 +80,8 @@ public final class Assignment_Statement extends Statement {
private static final String VALUEALREADYSET = "{0} value can only be assigned once";
private static final String BADCONSTANTASSIGNMENT = "Constant can only be initialized in a constructor";
private static final String HASNOSETTER = "Cannot assign a value to a property without a setter";
private final Reference reference;
private final TTCN3Template template;
......@@ -170,7 +174,7 @@ public final class Assignment_Statement extends Statement {
if (template == null) {
return;
}
switch (assignment.getAssignmentType()) {
case A_PAR_VAL_IN:
((FormalParameter) assignment).useAsLValue(reference);
......@@ -286,6 +290,15 @@ public final class Assignment_Statement extends Statement {
isErroneous = true;
return;
}
if (type instanceof Property_Type) {
Property_Type prop = (Property_Type)type;
if (prop.hasSetter() == false) {
getLocation().reportSemanticError(HASNOSETTER);
isErroneous = true;
return;
}
}
value.setMyGovernor(type);
IValue lastValue = type.checkThisValueRef(timestamp, value);
......
......@@ -28,7 +28,6 @@ import org.eclipse.titan.designer.AST.INamedNode;
import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.ISubReference;
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.NULL_Location;
import org.eclipse.titan.designer.AST.NamedBridgeScope;
......@@ -36,21 +35,17 @@ import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.ReferenceFinder;
import org.eclipse.titan.designer.AST.ReferenceFinder.Hit;
import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.Type;
import org.eclipse.titan.designer.AST.TTCN3.IAppendableSyntax;
import org.eclipse.titan.designer.AST.TTCN3.IIncrementallyUpdateable;
import org.eclipse.titan.designer.AST.TTCN3.TTCN3Scope;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Altstep;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Testcase;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Var;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition;
import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameter.parameterEvaluationType;
import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameterList;
import org.eclipse.titan.designer.AST.TTCN3.statements.Statement.Statement_type;
import org.eclipse.titan.designer.AST.TTCN3.types.ClassTypeBody;
import org.eclipse.titan.designer.AST.TTCN3.types.Component_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Integer_Type;
import org.eclipse.titan.designer.compiler.JavaGenData;
import org.eclipse.titan.designer.editors.ProposalCollector;
import org.eclipse.titan.designer.editors.SkeletonTemplateProposal;
......@@ -131,6 +126,9 @@ public final class StatementBlock extends TTCN3Scope implements ILocateableNode,
/** Indicates it is a statement block of a class property */
private boolean ownerIsProperty;
/** Indicates if it is a statement block of a property setter */
private boolean isPropertySetter;
/** Formal parameter list with only one member.
* It is used to support the special 'value' keyword in class properties
......@@ -1149,4 +1147,24 @@ public final class StatementBlock extends TTCN3Scope implements ILocateableNode,
public FormalParameterList getValueParamList() {
return valueParamList;
}
public boolean ownerIsProperty() {
return this.ownerIsProperty;
}
/**
* Checks wheter a statement block belongs to a property setter
* @return
*/
public boolean isPropertySetter() {
if (ownerIsProperty) {
return this.isPropertySetter;
}
return false;
}
public void setIsSetter() {
this.isPropertySetter = true;
}
}
......@@ -18,6 +18,7 @@ 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.Reference;
import org.eclipse.titan.designer.AST.ReferenceChain;
import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.Type;
import org.eclipse.titan.designer.AST.TypeCompatibilityInfo;
......@@ -41,6 +42,8 @@ public final class Property_Type extends Type {
private StatementBlock getStatementBlock;
private StatementBlock setStatementBlock;
private FormalParameterList fpList;
private boolean hasGetter;
private boolean hasSetter;
public Property_Type(Type type) {
this.myType = type;
......@@ -54,6 +57,7 @@ public final class Property_Type extends Type {
* @param sb
*/
public void setStatementBlockGetter(StatementBlock sb) {
hasGetter = true;
getStatementBlock = sb;
if (getStatementBlock != null) {
getStatementBlock.setOwnerIsProperty();
......@@ -66,8 +70,10 @@ public final class Property_Type extends Type {
* @param sb
*/
public void setStatementBlockSetter(StatementBlock sb) {
hasSetter = true;
setStatementBlock = sb;
if (setStatementBlock != null) {
setStatementBlock.setIsSetter();
setStatementBlock.setOwnerIsProperty();
setStatementBlock.setFullNameParent(this);
}
......@@ -82,7 +88,6 @@ public final class Property_Type extends Type {
fpList = new FormalParameterList(paramList);
if (getStatementBlock != null) {
getStatementBlock.setValueParamList(fpList);
getStatementBlock.check(timestamp);
}
if (setStatementBlock != null) {
......@@ -117,6 +122,17 @@ public final class Property_Type extends Type {
setStatementBlock.setMyScope(scope);
}
}
/** Checks whether the property has a setter definition
* @return
*/
public boolean hasSetter() {
return hasSetter;
}
public boolean hasGetter() {
return hasGetter;
}
@Override
public String getOutlineIcon() {
......@@ -130,6 +146,31 @@ public final class Property_Type extends Type {
return myType;
}
@Override
/** {@inheritDoc} */
public IType getTypeRefdLast(final CompilationTimeStamp timestamp) {
final IReferenceChain referenceChain = ReferenceChain.getInstance(IReferenceChain.CIRCULARREFERENCE, true);
final IType result = getTypeRefdLast(timestamp, referenceChain);
referenceChain.release();
return result;
}
/**
* Returns the type referred last in case of a referred type, or itself
* in any other case.
*
* @param timestamp
* the time stamp of the actual semantic check cycle.
* @param referenceChain
* the ReferenceChain used to detect circular references
*
* @return the actual or the last referred type
* */
public IType getTypeRefdLast(final CompilationTimeStamp timestamp, final IReferenceChain referenceChain) {
return this.myType;
}
@Override
public boolean checkThisTemplate(CompilationTimeStamp timestamp, ITTCN3Template template, boolean isModified,
boolean implicitOmit, Assignment lhs) {
......
......@@ -164,7 +164,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(84);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(85);
int lineNum = 32;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
......@@ -296,7 +296,7 @@ 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 += 12;
lineNum += 16;
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;
......@@ -308,6 +308,8 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("An abstract class cannot be instantiated", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 3;
markersToCheck.add(new MarkerToCheck("Private member is inaccessible due to its protection level", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 3;
markersToCheck.add(new MarkerToCheck("Cannot assign a value to a property without a setter", lineNum, IMarker.SEVERITY_ERROR));
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