@@ -119,11 +119,11 @@ public class EolStaticAnalyser implements IModuleValidator, IEolVisitor {
119
119
protected EolModule module ;
120
120
protected EolStaticAnalysisContext context = new EolStaticAnalysisContext ();
121
121
protected List <IStaticOperation > operations = new ArrayList <>();
122
- HashMap <Operation , Boolean > returnFlags = new HashMap <>(); // for every missmatch
122
+ HashMap <Operation , Boolean > returnFlags = new HashMap <>(); // for every missmatch
123
123
124
124
public EolStaticAnalyser () {
125
125
}
126
-
126
+
127
127
public EolStaticAnalyser (IModelFactory modelFactory ) {
128
128
context .modelFactory = modelFactory ;
129
129
}
@@ -167,8 +167,7 @@ public void visit(AssignmentStatement assignmentStatement) {
167
167
if (!targetType .isAncestorOf (valueType )) {
168
168
if (canBeCompatible (targetType , valueType )) {
169
169
createTypeCompatibilityWarning (targetExpression , valueExpression );
170
- }
171
- else {
170
+ } else {
172
171
createTypeCompatibilityError (targetExpression , valueExpression );
173
172
}
174
173
}
@@ -260,7 +259,7 @@ public void visit(ExpressionStatement expressionStatement) {
260
259
expressionStatement .getExpression ().accept (this );
261
260
262
261
}
263
-
262
+
264
263
@ Override
265
264
public void visit (FirstOrderOperationCallExpression firstOrderOperationCallExpression ) {
266
265
String name = firstOrderOperationCallExpression .getName ();
@@ -269,13 +268,12 @@ public void visit(FirstOrderOperationCallExpression firstOrderOperationCallExpre
269
268
errors .add (new ModuleMarker (firstOrderOperationCallExpression .getNameExpression (),
270
269
"Undefined first order operation " + name , Severity .Error ));
271
270
return ;
272
- };
271
+ }
273
272
TypeCalculator tc = operation .getClass ().getAnnotation (TypeCalculator .class );
274
273
if (tc == null ) {
275
274
setResolvedType (firstOrderOperationCallExpression , EolAnyType .Instance );
276
275
return ;
277
276
}
278
-
279
277
280
278
Expression targetExpression = firstOrderOperationCallExpression .getTargetExpression ();
281
279
targetExpression .accept (this );
@@ -297,7 +295,7 @@ public void visit(FirstOrderOperationCallExpression firstOrderOperationCallExpre
297
295
expression .accept (this );
298
296
EolType expressionType = getResolvedType (expression );
299
297
context .getFrameStack ().leaveLocal (firstOrderOperationCallExpression );
300
-
298
+
301
299
try {
302
300
EolType returnType = tc .klass ().newInstance ().calculateType (contextType , expressionType );
303
301
setResolvedType (firstOrderOperationCallExpression , returnType );
@@ -586,11 +584,11 @@ public void visit(OperationCallExpression operationCallExpression) {
586
584
for (Expression parameterExpression : parameterExpressions ) {
587
585
parameterExpression .accept (this );
588
586
}
589
-
590
- //Name check
587
+
588
+ // Name check
591
589
List <IStaticOperation > temp = new ArrayList <IStaticOperation >();
592
- for (IStaticOperation op : resolvedOperations ) {
593
- if (nameExpression .getName ().equals (op .getName ())) {
590
+ for (IStaticOperation op : resolvedOperations ) {
591
+ if (nameExpression .getName ().equals (op .getName ())) {
594
592
temp .add (op );
595
593
}
596
594
}
@@ -599,14 +597,13 @@ public void visit(OperationCallExpression operationCallExpression) {
599
597
errors .add (new ModuleMarker (nameExpression , "Undefined operation" , Severity .Error ));
600
598
return ;
601
599
}
602
-
603
- //Context check
600
+
601
+ // Context check
604
602
temp = new ArrayList <IStaticOperation >();
605
- for (IStaticOperation op : resolvedOperations ) {
603
+ for (IStaticOperation op : resolvedOperations ) {
606
604
EolType opContextType = op .getContextType ();
607
- if (contextType == opContextType ||
608
- opContextType .isAncestorOf (contextType ) ||
609
- canBeCompatible (opContextType , contextType )) {
605
+ if (contextType == opContextType || opContextType .isAncestorOf (contextType )
606
+ || canBeCompatible (opContextType , contextType )) {
610
607
temp .add (op );
611
608
}
612
609
}
@@ -617,10 +614,10 @@ public void visit(OperationCallExpression operationCallExpression) {
617
614
Severity .Error ));
618
615
return ;
619
616
}
620
-
617
+
621
618
// Number of parameters check
622
619
temp = new ArrayList <IStaticOperation >();
623
- for (IStaticOperation op : resolvedOperations ) {
620
+ for (IStaticOperation op : resolvedOperations ) {
624
621
List <EolType > reqParams = op .getParameterTypes ();
625
622
if (reqParams .size () == parameterExpressions .size ()) {
626
623
temp .add (op );
@@ -631,18 +628,17 @@ public void visit(OperationCallExpression operationCallExpression) {
631
628
errors .add (new ModuleMarker (nameExpression , "Parameter number mismatch" , Severity .Error ));
632
629
return ;
633
630
}
634
-
631
+
635
632
// Parameter type checks
636
633
temp = new ArrayList <IStaticOperation >();
637
- for (IStaticOperation op : resolvedOperations ) {
634
+ for (IStaticOperation op : resolvedOperations ) {
638
635
int index = 0 ;
639
636
List <EolType > reqParamTypess = op .getParameterTypes ();
640
637
boolean compatible = true ;
641
638
for (EolType reqParamType : reqParamTypess ) {
642
639
EolType provParamType = getResolvedType (parameterExpressions .get (index ));
643
640
index ++;
644
- if (!reqParamType .isAncestorOf (provParamType )
645
- && !canBeCompatible (reqParamType , provParamType )) {
641
+ if (!reqParamType .isAncestorOf (provParamType ) && !canBeCompatible (reqParamType , provParamType )) {
646
642
compatible = false ;
647
643
break ;
648
644
}
@@ -656,22 +652,22 @@ public void visit(OperationCallExpression operationCallExpression) {
656
652
errors .add (new ModuleMarker (nameExpression , "Parameters type mismatch" , Severity .Error ));
657
653
return ;
658
654
}
659
-
660
- //Process resolved operations
661
- Set <EolType > returnTypes = resolvedOperations .stream ()
662
- .map ( op -> op . getReturnType ()). collect (Collectors .toSet ());
663
- if (returnTypes .size () == 1 ){
664
- setResolvedType (operationCallExpression , (EolType )returnTypes .toArray ()[0 ]);
665
- }else {
655
+
656
+ // Process resolved operations
657
+ Set <EolType > returnTypes = resolvedOperations .stream (). map ( op -> op . getReturnType ())
658
+ .collect (Collectors .toSet ());
659
+ if (returnTypes .size () == 1 ) {
660
+ setResolvedType (operationCallExpression , (EolType ) returnTypes .toArray ()[0 ]);
661
+ } else {
666
662
setResolvedType (operationCallExpression , new EolUnionType (returnTypes ));
667
663
}
668
-
669
- //Check for warning related to subtypes
664
+
665
+ // Check for warning related to subtypes
670
666
Set <EolType > resolvedOperationContextTypes = new HashSet <EolType >();
671
667
for (IStaticOperation op : resolvedOperations ) {
672
668
resolvedOperationContextTypes .add (op .getContextType ());
673
669
}
674
-
670
+
675
671
Stack <EolType > stack = new Stack <EolType >();
676
672
stack .push (contextType );
677
673
outerLoop : while (!stack .isEmpty ()) {
@@ -775,7 +771,8 @@ else if (targetExpression instanceof NameExpression && ((NameExpression) targetE
775
771
collectionType .setContentType (toStaticAnalyserType (structuralFeature .getType ()));
776
772
setResolvedType (propertyCallExpression , collectionType );
777
773
} else {
778
- setResolvedType (propertyCallExpression , toStaticAnalyserType (structuralFeature .getType ()));
774
+ setResolvedType (propertyCallExpression ,
775
+ toStaticAnalyserType (structuralFeature .getType ()));
779
776
}
780
777
if (many ) {
781
778
setResolvedType (propertyCallExpression ,
@@ -1046,21 +1043,21 @@ public void operationPreVisitor(Operation operation) {
1046
1043
EolType contextType = EolNoType .Instance ;
1047
1044
TypeExpression returnTypeExpression = operation .getReturnTypeExpression ();
1048
1045
EolType returnType = EolAnyType .Instance ;
1049
-
1046
+
1050
1047
if (contextTypeExpression != null ) {
1051
1048
contextTypeExpression .accept (this );
1052
1049
contextType = getResolvedType (contextTypeExpression );
1053
1050
}
1054
-
1051
+
1055
1052
if (returnTypeExpression != null ) {
1056
1053
returnTypeExpression .accept (this );
1057
1054
returnType = getResolvedType (returnTypeExpression );
1058
1055
}
1059
-
1056
+
1060
1057
operation .getData ().put ("contextType" , contextType );
1061
1058
operation .getData ().put ("returnType" , returnType );
1062
1059
}
1063
-
1060
+
1064
1061
public void preValidate (IEolModule imodule ) {
1065
1062
1066
1063
EolModule eolModule = (EolModule ) imodule ;
@@ -1069,19 +1066,20 @@ public void preValidate(IEolModule imodule) {
1069
1066
for (ModelDeclaration modelDeclaration : module .getDeclaredModelDeclarations ()) {
1070
1067
modelDeclaration .accept (this );
1071
1068
}
1072
-
1069
+
1073
1070
module .getDeclaredOperations ().forEach (o -> operationPreVisitor (o ));
1074
1071
module .getDeclaredOperations ().forEach (o -> operations .add (new SimpleOperation (o )));
1075
1072
module .getDeclaredOperations ().forEach (o -> o .accept (this ));
1076
-
1077
- //Parse builtin operations
1078
- List <OperationContributor > operationContributors = context .operationContributorRegistry .stream ().collect (Collectors .toList ());
1079
- for (OperationContributor oc : operationContributors ) {
1073
+
1074
+ // Parse builtin operations
1075
+ List <OperationContributor > operationContributors = context .operationContributorRegistry .stream ()
1076
+ .collect (Collectors .toList ());
1077
+ for (OperationContributor oc : operationContributors ) {
1080
1078
EolType contextType = oc .contributesToType ();
1081
-
1082
- for (Method m : oc .getClass ().getDeclaredMethods ()) {
1079
+
1080
+ for (Method m : oc .getClass ().getDeclaredMethods ()) {
1083
1081
List <EolType > operationParameterTypes = new ArrayList <EolType >();
1084
- Type [] javaParameterTypes = m .getGenericParameterTypes ();
1082
+ Type [] javaParameterTypes = m .getGenericParameterTypes ();
1085
1083
for (Type javaParameterType : javaParameterTypes ) {
1086
1084
operationParameterTypes .add (javaTypeToEolType (javaParameterType ));
1087
1085
}
@@ -1090,37 +1088,33 @@ public void preValidate(IEolModule imodule) {
1090
1088
}
1091
1089
}
1092
1090
}
1093
-
1091
+
1094
1092
public EolType javaTypeToEolType (Type javaType ) {
1095
-
1093
+
1096
1094
if (javaType instanceof ParameterizedType ) {
1097
- Type rawType = ((ParameterizedType )javaType ).getRawType ();
1098
- Type [] typeArgs = ((ParameterizedType )javaType ).getActualTypeArguments ();
1099
- EolType eolType = javaClassToEolType ((Class <?>)rawType );
1100
- if (eolType instanceof EolCollectionType ){
1095
+ Type rawType = ((ParameterizedType ) javaType ).getRawType ();
1096
+ Type [] typeArgs = ((ParameterizedType ) javaType ).getActualTypeArguments ();
1097
+ EolType eolType = javaClassToEolType ((Class <?>) rawType );
1098
+ if (eolType instanceof EolCollectionType ) {
1101
1099
EolType contentType = javaTypeToEolType (typeArgs [0 ]);
1102
1100
eolType = new EolCollectionType (eolType .getName (), contentType );
1103
1101
return eolType ;
1104
- }
1105
- else if (eolType instanceof EolMapType ) {
1102
+ } else if (eolType instanceof EolMapType ) {
1106
1103
EolType keyType = javaTypeToEolType (typeArgs [0 ]);
1107
1104
EolType valueType = javaTypeToEolType (typeArgs [1 ]);
1108
1105
eolType = new EolMapType (keyType , valueType );
1109
1106
return eolType ;
1110
- }
1111
- else {
1107
+ } else {
1112
1108
return EolAnyType .Instance ;
1113
1109
}
1114
- }
1115
- else if (javaType instanceof Class <?>) {
1110
+ } else if (javaType instanceof Class <?>) {
1116
1111
Class <?> javaClass = (Class <?>) javaType ;
1117
1112
return javaClassToEolType (javaClass );
1118
- }
1119
- else {
1113
+ } else {
1120
1114
return EolAnyType .Instance ;
1121
1115
}
1122
1116
}
1123
-
1117
+
1124
1118
public EolType javaClassToEolType (Class <?> javaClass ) {
1125
1119
if (javaClass == String .class || javaClass == char .class ) {
1126
1120
return EolPrimitiveType .String ;
@@ -1209,35 +1203,35 @@ public boolean canBeCompatible(EolType targetType, EolType valueType) {
1209
1203
if (targetType == null || valueType == null ) {
1210
1204
return false ;
1211
1205
}
1212
-
1206
+
1213
1207
if (valueType instanceof EolUnionType ) {
1214
1208
EolType tempType ;
1215
- for (EolType t : ((EolUnionType )valueType ).containedTypes ) {
1209
+ for (EolType t : ((EolUnionType ) valueType ).containedTypes ) {
1216
1210
tempType = targetType ;
1217
- while (true ) {
1211
+ while (true ) {
1218
1212
if (tempType instanceof EolAnyType ) {
1219
1213
break ;
1220
1214
}
1221
1215
if (t .equals (tempType )) {
1222
1216
return true ;
1223
-
1217
+
1224
1218
} else {
1225
1219
tempType = getParentType (tempType );
1226
1220
}
1227
1221
}
1228
1222
}
1229
1223
return false ;
1230
1224
}
1231
-
1225
+
1232
1226
if (targetType instanceof EolUnionType ) {
1233
- for (EolType t : ((EolUnionType )targetType ).containedTypes ) {
1227
+ for (EolType t : ((EolUnionType ) targetType ).containedTypes ) {
1234
1228
if (canBeCompatible (t , valueType )) {
1235
1229
return true ;
1236
1230
}
1237
1231
}
1238
1232
return false ;
1239
1233
}
1240
-
1234
+
1241
1235
while (true ) {
1242
1236
1243
1237
if (!(targetType .equals (valueType )) && !(valueType instanceof EolAnyType )) {
@@ -1294,6 +1288,7 @@ public void visitOperatorExpression(OperatorExpression operatorExpression) {
1294
1288
firstOperand .accept (this );
1295
1289
if (secondOperand != null )
1296
1290
secondOperand .accept (this );
1291
+ List <EolType > operandTypes = operands .stream ().map (o -> getResolvedType (o )).collect (Collectors .toList ());
1297
1292
1298
1293
if (StringUtil .isOneOf (operator , "and" , "or" , "xor" , "not" , "implies" )) {
1299
1294
for (Expression operand : operatorExpression .getOperands ()) {
@@ -1326,21 +1321,19 @@ && getResolvedType(operand) != EolPrimitiveType.Real) {
1326
1321
}
1327
1322
1328
1323
if (StringUtil .isOneOf (operator , "+" )) {
1329
- for (Expression operand : operands ) {
1330
- if (getResolvedType (operand ) == EolPrimitiveType .String ) {
1331
- setResolvedType (operatorExpression , EolPrimitiveType .String );
1332
- break ;
1333
- }
1334
-
1335
- if (getResolvedType (operand ) == EolPrimitiveType .Integer )
1336
- setResolvedType (operatorExpression , EolPrimitiveType .Integer );
1337
-
1338
- if (getResolvedType (operand ) == EolPrimitiveType .Real )
1324
+ if (operandTypes .stream ().allMatch (
1325
+ t -> t .equals (EolNativeType .Number ) || t .equals (EolPrimitiveType .Real ) || t .equals (EolPrimitiveType .Integer ))) {
1326
+ if (operandTypes .contains (EolNativeType .Number ))
1327
+ setResolvedType (operatorExpression , EolNativeType .Number );
1328
+ else if (operandTypes .contains (EolPrimitiveType .Real ))
1339
1329
setResolvedType (operatorExpression , EolPrimitiveType .Real );
1340
- }
1341
-
1330
+ else
1331
+ setResolvedType (operatorExpression , EolPrimitiveType .Integer );
1332
+ }else if (operandTypes .stream ().allMatch (t -> t instanceof EolCollectionType ))
1333
+ setResolvedType (operatorExpression , operandTypes .get (0 ));
1334
+ else
1335
+ setResolvedType (operatorExpression , EolPrimitiveType .String );
1342
1336
}
1343
-
1344
1337
}
1345
1338
1346
1339
public boolean hasReturnStatement (Operation operation ) {
@@ -1462,7 +1455,7 @@ public EolModelElementType getModelElementType(String modelAndType, AbstractModu
1462
1455
}
1463
1456
1464
1457
}
1465
-
1458
+
1466
1459
private EolType toStaticAnalyserType (org .eclipse .epsilon .eol .types .EolType type ) {
1467
1460
if (type == null ) {
1468
1461
return null ;
0 commit comments