@@ -1181,6 +1181,10 @@ redef class AAttrPropdef
1181
1181
# Could be through `n_expr`, `n_block` or `is_lazy`
1182
1182
var has_value = false
1183
1183
1184
+ # The name of the attribute
1185
+ # Note: The name of the attribute is in reality the name of the mreadpropdef
1186
+ var name : String = n_id2 .text is lazy
1187
+
1184
1188
# The guard associated to a lazy attribute.
1185
1189
# Because some engines does not have a working `isset`,
1186
1190
# this additional attribute is used to guard the lazy initialization.
@@ -1195,48 +1199,14 @@ redef class AAttrPropdef
1195
1199
redef fun build_property (modelbuilder , mclassdef )
1196
1200
do
1197
1201
var mclass = mclassdef .mclass
1198
- var nid2 = n_id2
1199
- var name = nid2 .text
1200
1202
1201
1203
var atabstract = self .get_single_annotation ("abstract " , modelbuilder )
1202
- if atabstract == null then
1203
- if not mclass .kind .need_init then
1204
- modelbuilder .error (self , "Error: attempt to define attribute ` {name } ` in the {mclass .kind } ` {mclass } `. " )
1205
- end
1206
1204
1207
- var mprop = new MAttribute (mclassdef , "_ " + name , self .location , private_visibility )
1208
- var mpropdef = new MAttributeDef (mclassdef , mprop , self .location )
1209
- self .mpropdef = mpropdef
1210
- modelbuilder .mpropdef2npropdef [mpropdef ] = self
1211
- end
1205
+ if atabstract == null then build_attribute_property (modelbuilder , mclassdef )
1212
1206
1213
- var readname = name
1214
- var mreadprop = modelbuilder .try_get_mproperty_by_name (nid2 , mclassdef , readname ).as (nullable MMethod )
1215
- if mreadprop == null then
1216
- var mvisibility = new_property_visibility (modelbuilder , mclassdef , self .n_visibility )
1217
- mreadprop = new MMethod (mclassdef , readname , self .location , mvisibility )
1218
- if not self .check_redef_keyword (modelbuilder , mclassdef , n_kwredef , false , mreadprop ) then
1219
- mreadprop .is_broken = true
1220
- return
1221
- end
1222
- else
1223
- if mreadprop .is_broken then return
1224
- if not self .check_redef_keyword (modelbuilder , mclassdef , n_kwredef , true , mreadprop ) then return
1225
- check_redef_property_visibility (modelbuilder , self .n_visibility , mreadprop )
1226
- end
1227
- mclassdef .mprop2npropdef [mreadprop ] = self
1228
-
1229
- var attr_mpropdef = mpropdef
1230
- if attr_mpropdef != null then
1231
- mreadprop .getter_for = attr_mpropdef .mproperty
1232
- attr_mpropdef .mproperty .getter = mreadprop
1233
- end
1207
+ # Construction of the read property. If it's not correctly built just return.
1208
+ if not build_read_property (modelbuilder , mclassdef ) then return
1234
1209
1235
- var mreadpropdef = new MMethodDef (mclassdef , mreadprop , self .location )
1236
- self .mreadpropdef = mreadpropdef
1237
- modelbuilder .mpropdef2npropdef [mreadpropdef ] = self
1238
- set_doc (mreadpropdef , modelbuilder )
1239
- if mpropdef != null then mpropdef .mdoc = mreadpropdef .mdoc
1240
1210
if atabstract != null then mreadpropdef .is_abstract = true
1241
1211
1242
1212
has_value = n_expr != null or n_block != null
@@ -1259,29 +1229,8 @@ redef class AAttrPropdef
1259
1229
end
1260
1230
end
1261
1231
1262
- var atlazy = self .get_single_annotation ("lazy " , modelbuilder )
1263
- var atlateinit = self .get_single_annotation ("lateinit " , modelbuilder )
1264
- if atlazy != null or atlateinit != null then
1265
- if atlazy != null and atlateinit != null then
1266
- modelbuilder .error (atlazy , "Error: `lazy` incompatible with `lateinit`. " )
1267
- return
1268
- end
1269
- if not has_value then
1270
- if atlazy != null then
1271
- modelbuilder .error (atlazy , "Error: `lazy` attributes need a value. " )
1272
- else if atlateinit != null then
1273
- modelbuilder .error (atlateinit , "Error: `lateinit` attributes need a value. " )
1274
- end
1275
- has_value = true
1276
- return
1277
- end
1278
- is_lazy = true
1279
- var mlazyprop = new MAttribute (mclassdef , "lazy _ " + name , self .location , none_visibility )
1280
- mlazyprop .is_fictive = true
1281
- var mlazypropdef = new MAttributeDef (mclassdef , mlazyprop , self .location )
1282
- mlazypropdef .is_fictive = true
1283
- self .mlazypropdef = mlazypropdef
1284
- end
1232
+ # Construction of the read property. If it's not correctly built just return.
1233
+ if not build_lazy_property (modelbuilder , mclassdef ) then return
1285
1234
1286
1235
var atoptional = self .get_single_annotation ("optional " , modelbuilder )
1287
1236
if atoptional != null then
@@ -1304,40 +1253,123 @@ redef class AAttrPropdef
1304
1253
modelbuilder .advice (self , "attr-in-refinement " , "Warning: attributes in refinement need a value or `noautoinit`. " )
1305
1254
end
1306
1255
1256
+ # Construction of the read property. If it's not correctly built just return.
1257
+ if not build_write_property (modelbuilder , mclassdef , false ) then return
1258
+
1259
+ if atabstract != null then mwritepropdef .is_abstract = true
1260
+
1261
+ var atautoinit = self .get_single_annotation ("autoinit " , modelbuilder )
1262
+ if atautoinit != null then
1263
+ if has_value then
1264
+ modelbuilder .error (atautoinit , "Error: `autoinit` attributes cannot have an initial value. " )
1265
+ else if not mwritepropdef .is_intro then
1266
+ modelbuilder .error (atautoinit , "Error: `autoinit` attributes cannot be set on redefinitions. " )
1267
+ else if not mclassdef .is_intro then
1268
+ modelbuilder .error (atautoinit , "Error: `autoinit` attributes cannot be used in class refinements. " )
1269
+ else if atabstract == null then
1270
+ modelbuilder .warning (atautoinit , "useless-autoinit " , "Warning: superfluous `autoinit` on attribute. " )
1271
+ end
1272
+ else if atabstract != null then
1273
+ # By default, abstract attribute are not autoinit
1274
+ noinit = true
1275
+ end
1276
+ end
1277
+
1278
+ # Build the attribute property
1279
+ fun build_attribute_property (modelbuilder : ModelBuilder , mclassdef : MClassDef )
1280
+ do
1281
+ var mclass = mclassdef .mclass
1282
+ var attribute_name = "_ " + name
1283
+
1284
+ if not mclass .kind .need_init then
1285
+ modelbuilder .error (self , "Error: attempt to define attribute ` {name } ` in the {mclass .kind } ` {mclass } `. " )
1286
+ end
1287
+ var mprop = new MAttribute (mclassdef , "_ " + name , self .location , private_visibility )
1288
+ var mpropdef = new MAttributeDef (mclassdef , mprop , self .location )
1289
+ self .mpropdef = mpropdef
1290
+ modelbuilder .mpropdef2npropdef [mpropdef ] = self
1291
+ end
1292
+
1293
+ # Build the read method property to get the value of the attribute
1294
+ # Return `true` if the property was correctly created else return `false`.
1295
+ # Warning the signature of the property is not set. This step is done by `build_signature`.
1296
+ fun build_read_property (modelbuilder : ModelBuilder , mclassdef : MClassDef ): Bool
1297
+ do
1298
+ var mclass = mclassdef .mclass
1299
+
1300
+ var readname = name
1301
+ var mreadprop = modelbuilder .try_get_mproperty_by_name (self , mclassdef , readname ).as (nullable MMethod )
1302
+ if mreadprop == null then
1303
+ var mvisibility = new_property_visibility (modelbuilder , mclassdef , self .n_visibility )
1304
+ mreadprop = new MMethod (mclassdef , readname , self .location , mvisibility )
1305
+ if not self .check_redef_keyword (modelbuilder , mclassdef , n_kwredef , false , mreadprop ) then
1306
+ mreadprop .is_broken = true
1307
+ return false
1308
+ end
1309
+ else
1310
+ if mreadprop .is_broken then return false
1311
+ if not self .check_redef_keyword (modelbuilder , mclassdef , n_kwredef , true , mreadprop ) then return false
1312
+ check_redef_property_visibility (modelbuilder , self .n_visibility , mreadprop )
1313
+ end
1314
+ mclassdef .mprop2npropdef [mreadprop ] = self
1315
+
1316
+ var attr_mpropdef = mpropdef
1317
+ if attr_mpropdef != null then
1318
+ mreadprop .getter_for = attr_mpropdef .mproperty
1319
+ attr_mpropdef .mproperty .getter = mreadprop
1320
+ end
1321
+
1322
+ var mreadpropdef = new MMethodDef (mclassdef , mreadprop , self .location )
1323
+ self .mreadpropdef = mreadpropdef
1324
+ modelbuilder .mpropdef2npropdef [mreadpropdef ] = self
1325
+ set_doc (mreadpropdef , modelbuilder )
1326
+ if mpropdef != null then mpropdef .mdoc = mreadpropdef .mdoc
1327
+
1328
+ return true
1329
+ end
1330
+
1331
+ # Build the write method property to set the attribute value
1332
+ # Return `true` if the property was correctly created else return `false`.
1333
+ # Warning the signature of the property is not set.
1334
+ fun build_write_property (modelbuilder : ModelBuilder , mclassdef : MClassDef , is_same_visibility : Bool ): Bool
1335
+ do
1336
+ var mclass = mclassdef .mclass
1337
+
1307
1338
var writename = name + "= "
1308
1339
var atwritable = self .get_single_annotation ("writable " , modelbuilder )
1309
1340
if atwritable != null then
1310
1341
if not atwritable .n_args .is_empty then
1311
1342
writename = atwritable .arg_as_id (modelbuilder ) or else writename
1312
1343
end
1313
1344
end
1314
- var mwriteprop = modelbuilder .try_get_mproperty_by_name (nid2 , mclassdef , writename ).as (nullable MMethod )
1345
+ var mwriteprop = modelbuilder .try_get_mproperty_by_name (self , mclassdef , writename ).as (nullable MMethod )
1315
1346
var nwkwredef : nullable Token = null
1316
1347
if atwritable != null then nwkwredef = atwritable .n_kwredef
1317
1348
if mwriteprop == null then
1318
1349
var mvisibility
1319
1350
if atwritable != null then
1320
1351
mvisibility = new_property_visibility (modelbuilder , mclassdef , atwritable .n_visibility )
1321
1352
else
1322
- mvisibility = mreadprop .visibility
1353
+ mvisibility = mreadpropdef . mproperty .visibility
1323
1354
# By default, use protected visibility at most
1324
- if mvisibility > protected_visibility then mvisibility = protected_visibility
1355
+ if mvisibility > protected_visibility and not is_same_visibility then mvisibility = protected_visibility
1325
1356
end
1326
1357
mwriteprop = new MMethod (mclassdef , writename , self .location , mvisibility )
1327
1358
if not self .check_redef_keyword (modelbuilder , mclassdef , nwkwredef , false , mwriteprop ) then
1328
1359
mwriteprop .is_broken = true
1329
- return
1360
+ return false
1330
1361
end
1331
- mwriteprop .deprecation = mreadprop .deprecation
1362
+ mwriteprop .deprecation = mreadpropdef . mproperty .deprecation
1332
1363
else
1333
- if mwriteprop .is_broken then return
1334
- if not self .check_redef_keyword (modelbuilder , mclassdef , nwkwredef or else n_kwredef , true , mwriteprop ) then return
1364
+ if mwriteprop .is_broken then return false
1365
+ if not self .check_redef_keyword (modelbuilder , mclassdef , nwkwredef or else n_kwredef , true , mwriteprop ) then return false
1335
1366
if atwritable != null then
1336
1367
check_redef_property_visibility (modelbuilder , atwritable .n_visibility , mwriteprop )
1337
1368
end
1338
1369
end
1339
1370
mclassdef .mprop2npropdef [mwriteprop ] = self
1340
1371
1372
+ var attr_mpropdef = mpropdef
1341
1373
if attr_mpropdef != null then
1342
1374
mwriteprop .setter_for = attr_mpropdef .mproperty
1343
1375
attr_mpropdef .mproperty .setter = mwriteprop
@@ -1347,23 +1379,40 @@ redef class AAttrPropdef
1347
1379
self .mwritepropdef = mwritepropdef
1348
1380
modelbuilder .mpropdef2npropdef [mwritepropdef ] = self
1349
1381
mwritepropdef .mdoc = mreadpropdef .mdoc
1350
- if atabstract != null then mwritepropdef .is_abstract = true
1351
1382
1352
- var atautoinit = self .get_single_annotation ("autoinit " , modelbuilder )
1353
- if atautoinit != null then
1354
- if has_value then
1355
- modelbuilder .error (atautoinit , "Error: `autoinit` attributes cannot have an initial value. " )
1356
- else if not mwritepropdef .is_intro then
1357
- modelbuilder .error (atautoinit , "Error: `autoinit` attributes cannot be set on redefinitions. " )
1358
- else if not mclassdef .is_intro then
1359
- modelbuilder .error (atautoinit , "Error: `autoinit` attributes cannot be used in class refinements. " )
1360
- else if atabstract == null then
1361
- modelbuilder .warning (atautoinit , "useless-autoinit " , "Warning: superfluous `autoinit` on attribute. " )
1383
+ return true
1384
+ end
1385
+
1386
+ # Build the lazy attribute property
1387
+ # Return `true` if the property was correctly created else return `false`.
1388
+ fun build_lazy_property (modelbuilder : ModelBuilder , mclassdef : MClassDef ): Bool
1389
+ do
1390
+ var mclass = mclassdef .mclass
1391
+
1392
+ var atlazy = self .get_single_annotation ("lazy " , modelbuilder )
1393
+ var atlateinit = self .get_single_annotation ("lateinit " , modelbuilder )
1394
+ if atlazy != null or atlateinit != null then
1395
+ if atlazy != null and atlateinit != null then
1396
+ modelbuilder .error (atlazy , "Error: `lazy` incompatible with `lateinit`. " )
1397
+ return false
1362
1398
end
1363
- else if atabstract != null then
1364
- # By default, abstract attribute are not autoinit
1365
- noinit = true
1399
+ if not has_value then
1400
+ if atlazy != null then
1401
+ modelbuilder .error (atlazy , "Error: `lazy` attributes need a value. " )
1402
+ else if atlateinit != null then
1403
+ modelbuilder .error (atlateinit , "Error: `lateinit` attributes need a value. " )
1404
+ end
1405
+ has_value = true
1406
+ return false
1407
+ end
1408
+ is_lazy = true
1409
+ var mlazyprop = new MAttribute (mclassdef , "lazy _ " + name , self .location , none_visibility )
1410
+ mlazyprop .is_fictive = true
1411
+ var mlazypropdef = new MAttributeDef (mclassdef , mlazyprop , self .location )
1412
+ mlazypropdef .is_fictive = true
1413
+ self .mlazypropdef = mlazypropdef
1366
1414
end
1415
+ return true
1367
1416
end
1368
1417
1369
1418
redef fun build_signature (modelbuilder )
@@ -1421,23 +1470,9 @@ redef class AAttrPropdef
1421
1470
mpropdef .static_mtype = mtype
1422
1471
end
1423
1472
1424
- do
1425
- var msignature = new MSignature (new Array [MParameter ], mtype )
1426
- mreadpropdef .msignature = msignature
1427
- end
1473
+ build_read_signature
1428
1474
1429
- var mwritepropdef = self .mwritepropdef
1430
- if mwritepropdef != null then
1431
- var mwritetype = mtype
1432
- if is_optional then
1433
- mwritetype = mwritetype .as_nullable
1434
- end
1435
- var name : String
1436
- name = n_id2 .text
1437
- var mparameter = new MParameter (name , mwritetype , false )
1438
- var msignature = new MSignature ([mparameter ], null )
1439
- mwritepropdef .msignature = msignature
1440
- end
1475
+ if self .mwritepropdef != null then build_write_signature
1441
1476
1442
1477
var mlazypropdef = self .mlazypropdef
1443
1478
if mlazypropdef != null then
@@ -1446,6 +1481,33 @@ redef class AAttrPropdef
1446
1481
check_repeated_types (modelbuilder )
1447
1482
end
1448
1483
1484
+ # Build the read method signature
1485
+ # `except`: mreadpropdef != null
1486
+ # `expect`: mtype != null
1487
+ fun build_read_signature
1488
+ is
1489
+ expect (mreadpropdef != null and mtype != null )
1490
+ do
1491
+ var msignature = new MSignature (new Array [MParameter ], mtype )
1492
+ mreadpropdef .msignature = msignature
1493
+ end
1494
+
1495
+ # Build the write method signature
1496
+ # `except`: mwritepropdef != null
1497
+ # `expect`: mtype != null
1498
+ fun build_write_signature
1499
+ is
1500
+ expect (mwritepropdef != null and mtype != null )
1501
+ do
1502
+ var mwritetype = mtype .as (not null )
1503
+ if is_optional then
1504
+ mwritetype = mwritetype .as_nullable
1505
+ end
1506
+ var mparameter = new MParameter (name , mwritetype , false )
1507
+ var msignature = new MSignature ([mparameter ], null )
1508
+ mwritepropdef .msignature = msignature
1509
+ end
1510
+
1449
1511
# Detect the static type from the value assigned to the attribute `self`
1450
1512
#
1451
1513
# Return the static type if it can be safely inferred.
0 commit comments