@@ -183,10 +183,9 @@ fun identifier_prefixes(
183
183
|" Exc_2 : exception; -- FLAG
184
184
|" end Foo;
185
185
{
186
- val str_prefix = " does not start with ";
187
-
188
186
fun check_exclusive(
189
- str,
187
+ name,
188
+ expected_prefix,
190
189
type_exclusive=true,
191
190
concurrent_exclusive=true,
192
191
access_exclusive=true,
@@ -196,26 +195,75 @@ fun identifier_prefixes(
196
195
exception_exclusive=true,
197
196
enum_exclusive=true
198
197
) =
199
- exclusive
200
- and (
201
- (type_exclusive and str.starts_with(type))
202
- or (concurrent_exclusive and str.starts_with(concurrent))
203
- or (access_exclusive and str.starts_with(access))
204
- or (class_access_exclusive and str.starts_with(class_access))
205
- or (subprogram_access_exclusive and str.starts_with(subprogram_access))
206
- or (constant_exclusive and str.starts_with(constant))
207
- or (exception_exclusive and str.starts_with(exception))
208
- or (enum_exclusive and str.starts_with(enum))
209
- );
198
+ |" If the ``exclusive`` rule's parameter is ``true``, this function
199
+ |" checks whether ``str`` starts with one of the provided prefixes and
200
+ |" returns a diagnostic string if so. Else it return unit.
201
+ |" Use ``xxx_exclusive`` parameters to exempt checking on a precise
202
+ |" prefix.
203
+ if exclusive
204
+ then [
205
+ name.text & " is not " & s[3] & " but starts with " & s[2]
206
+ for s in [
207
+ (concurrent_exclusive, concurrent, "a concurrent"),
208
+ (class_access_exclusive, class_access, "an access-to-class"),
209
+ (subprogram_access_exclusive, subprogram_access, "an access-to-subprogram"),
210
+ (access_exclusive, access, "an access"),
211
+ (type_exclusive, type, "a type"),
212
+ (constant_exclusive, constant, "a constant"),
213
+ (exception_exclusive, exception, "an exception"),
214
+ (enum_exclusive, enum, "an enumeration")
215
+ ]
216
+ if (
217
+ s[1]
218
+ and name.f_name.text.starts_with(s[2])
219
+ and not expected_prefix.starts_with(s[2])
220
+ )
221
+ ]?[1]
222
+ else ();
210
223
211
- fun check_enum(str) =
224
+ fun check_prefix_and_exclusive(
225
+ name,
226
+ expected_prefix,
227
+ prefix_kind,
228
+ check_previous_part_on=null,
229
+ type_exclusive=true,
230
+ concurrent_exclusive=true,
231
+ access_exclusive=true,
232
+ class_access_exclusive=true,
233
+ subprogram_access_exclusive=true,
234
+ constant_exclusive=true,
235
+ exception_exclusive=true,
236
+ enum_exclusive=true
237
+ ) =
212
238
if (
213
- (enum != "-" and not str.starts_with(enum))
214
- or check_exclusive(str, enum_exclusive=false)
239
+ if check_previous_part_on is not null
240
+ then check_previous_part_on.p_previous_part() is (null | IncompleteTypeDecl)
241
+ ) then (
242
+ if expected_prefix != "-" and not name.f_name.text.starts_with(expected_prefix)
243
+ then name.text & " does not start with " & prefix_kind & " prefix " & expected_prefix
244
+ else check_exclusive(
245
+ name,
246
+ expected_prefix,
247
+ type_exclusive,
248
+ concurrent_exclusive,
249
+ access_exclusive,
250
+ class_access_exclusive,
251
+ subprogram_access_exclusive,
252
+ constant_exclusive,
253
+ exception_exclusive,
254
+ enum_exclusive
255
+ )
215
256
)
216
- then str_prefix & "enumeration prefix " & enum
217
257
else ();
218
258
259
+ fun check_enum(name) =
260
+ check_prefix_and_exclusive(
261
+ name,
262
+ enum,
263
+ "enumeration",
264
+ enum_exclusive=false
265
+ );
266
+
219
267
@memoized
220
268
fun get_derived(t) = {
221
269
|" Return the element from derived corresponding to t, if any, or ""
@@ -225,7 +273,7 @@ fun identifier_prefixes(
225
273
if not res then "" else res[res.length]
226
274
};
227
275
228
- fun check_prefix (name) =
276
+ fun check_name (name) =
229
277
|" Given a DefiningName, check that it is validating all expressed
230
278
|" prefix constraints. Returns a string containing the message
231
279
|" explaining the constraint violation if the defining name is
@@ -237,14 +285,13 @@ fun identifier_prefixes(
237
285
when p is not SingleTaskTypeDecl
238
286
and concurrent != "-"
239
287
=>
240
- if (
241
- p.p_previous_part() is (null | IncompleteTypeDecl) and (
242
- not name.f_name.text.starts_with(concurrent)
243
- or check_exclusive(name.f_name.text, concurrent_exclusive=false)
244
- )
288
+ check_prefix_and_exclusive(
289
+ name,
290
+ concurrent,
291
+ "concurrent",
292
+ check_previous_part_on=p,
293
+ concurrent_exclusive=false
245
294
)
246
- then str_prefix & "concurrent prefix " & concurrent
247
- else ()
248
295
249
296
# 'Class access
250
297
| (
@@ -254,14 +301,13 @@ fun identifier_prefixes(
254
301
)
255
302
) when class_access != "-"
256
303
=>
257
- if (
258
- p.p_previous_part() is (null | IncompleteTypeDecl) and (
259
- not name.f_name.text.starts_with(class_access)
260
- or check_exclusive(name.f_name.text, class_access_exclusive=false)
261
- )
304
+ check_prefix_and_exclusive(
305
+ name,
306
+ class_access,
307
+ "access-to-class",
308
+ check_previous_part_on=p,
309
+ class_access_exclusive=false
262
310
)
263
- then str_prefix & "access-to-class prefix " & class_access
264
- else ()
265
311
266
312
# Subprogram access
267
313
| (
@@ -271,14 +317,13 @@ fun identifier_prefixes(
271
317
)
272
318
) when subprogram_access != "-"
273
319
=>
274
- if (
275
- p.p_previous_part() is (null | IncompleteTypeDecl) and (
276
- not name.f_name.text.starts_with(subprogram_access)
277
- or check_exclusive(name.f_name.text, subprogram_access_exclusive=false)
278
- )
320
+ check_prefix_and_exclusive(
321
+ name,
322
+ subprogram_access,
323
+ "access-to-subprogram",
324
+ check_previous_part_on=p,
325
+ subprogram_access_exclusive=false
279
326
)
280
- then str_prefix & "access-to-subprogram prefix " & subprogram_access
281
- else ()
282
327
283
328
# Other access types
284
329
| (
@@ -288,22 +333,18 @@ fun identifier_prefixes(
288
333
)
289
334
) when access != "-"
290
335
=>
291
- if (
292
- p.p_previous_part() is (null | IncompleteTypeDecl) and (
293
- not name.f_name.text.starts_with(access)
294
- or check_exclusive(
295
- name.f_name.text,
296
- access_exclusive=false,
297
- # If both an Access prefix and a Type prefix are
298
- # set and the type prefix is a prefix of the access
299
- # prefix, we don't want to flag this access because
300
- # it broke the exclusivity of the type prefix.
301
- type_exclusive=false
302
- )
303
- )
336
+ check_prefix_and_exclusive(
337
+ name,
338
+ access,
339
+ "access",
340
+ check_previous_part_on=p,
341
+ # If both an Access prefix and a Type prefix are set and the
342
+ # type prefix is a prefix of the access prefix, we don't
343
+ # want to flag this access because it broke the exclusivity
344
+ # of the type prefix.
345
+ access_exclusive=false,
346
+ type_exclusive=false
304
347
)
305
- then str_prefix & "access prefix " & access
306
- else ()
307
348
308
349
# (Sub)Types derived from `derived`
309
350
| p@(TypeDecl(f_type_def: DerivedTypeDef) | SubtypeDecl)
@@ -312,14 +353,14 @@ fun identifier_prefixes(
312
353
when get_derived(t) != ""
313
354
=> {
314
355
val derived_res = get_derived(p.p_canonical_type().p_base_type());
315
- if (
316
- p.p_previous_part() is (null | IncompleteTypeDecl) and (
317
- derived_res != ""
318
- and not name.f_name.text.starts_with(derived_res.split(":")[2])
319
- )
356
+ if derived_res != ""
357
+ then check_prefix_and_exclusive(
358
+ name,
359
+ derived_res.split(":")[2],
360
+ "derived",
361
+ check_previous_part_on=p
320
362
)
321
- then str_prefix & "derived prefix " & derived_res.split(":")[2]
322
- else ()
363
+ else check_exclusive(name, "")
323
364
}
324
365
325
366
# Exclude IncompleteTypeDecl
@@ -329,17 +370,16 @@ fun identifier_prefixes(
329
370
| p@BaseTypeDecl
330
371
when p is not SingleTaskTypeDecl
331
372
=>
332
- if (
333
- p.p_previous_part() is (null | IncompleteTypeDecl) and (
334
- (type != "-" and not name.f_name.text.starts_with(type))
335
- or check_exclusive(name.f_name.text, type_exclusive=false)
336
- )
373
+ check_prefix_and_exclusive(
374
+ name,
375
+ type,
376
+ "subtype",
377
+ check_previous_part_on=p,
378
+ type_exclusive=false
337
379
)
338
- then str_prefix & "subtype prefix " & type
339
- else ()
340
380
341
381
# Enums
342
- | EnumLiteralDecl => check_enum(name.f_name.text )
382
+ | EnumLiteralDecl => check_enum(name)
343
383
344
384
# Look one level up for remaining cases
345
385
| p => match p.parent
@@ -348,50 +388,45 @@ fun identifier_prefixes(
348
388
ObjectDecl(p_is_constant_object(): true)
349
389
| NumberDecl
350
390
) =>
351
- if (
352
- name.p_previous_part() is null and (
353
- (constant != "-" and not name.f_name.text.starts_with(constant))
354
- or check_exclusive(name.f_name.text, constant_exclusive=false)
355
- )
391
+ check_prefix_and_exclusive(
392
+ name,
393
+ constant,
394
+ "constant",
395
+ check_previous_part_on=name,
396
+ constant_exclusive=false
356
397
)
357
- then str_prefix & "constant prefix " & constant
358
- else ()
359
-
360
398
361
399
# Function renaming an enum literal
362
400
| r@SubpRenamingDecl
363
401
when r.f_renames?.f_renamed_object?.p_referenced_decl?() is EnumLiteralDecl
364
402
=>
365
- check_enum(name.f_name.text )
403
+ check_enum(name)
366
404
367
405
# Exceptions
368
406
| ExceptionDecl =>
369
- if (
370
- (exception != "-" and not name.f_name.text.starts_with(exception))
371
- or check_exclusive(name.f_name.text, exception_exclusive=false)
407
+ check_prefix_and_exclusive(
408
+ name,
409
+ exception,
410
+ "exception",
411
+ exception_exclusive=false
372
412
)
373
- then str_prefix & "exception prefix " & exception
374
- else ()
375
413
376
414
# Avoid checking declaration completions
377
415
| p@(BodyNode | SubpRenamingDecl | ObjectDecl) => {
378
416
val n = if p is ObjectDecl then name else p;
379
- if n.p_previous_part() is null and check_exclusive(name.f_name.text )
380
- then " does not have an exclusive prefix"
417
+ if n.p_previous_part() is ( null | IncompleteTypeDecl )
418
+ then check_exclusive(name, "")
381
419
else ()
382
420
}
383
421
384
422
# All other cases, check the exclusivity
385
- | * =>
386
- if check_exclusive(name.f_name.text)
387
- then " does not have an exclusive prefix"
388
- else ();
423
+ | * => check_exclusive(name, "");
389
424
390
425
# Iterate over all defining names and check prefixes for each
391
426
[
392
- {message: s[1].text & s[ 2], loc: s[1]}
427
+ {message: s[2], loc: s[1]}
393
428
for s in [
394
- (n, check_prefix (n))
429
+ (n, check_name (n))
395
430
for n in from unit.root select DefiningName
396
431
]
397
432
if s[2] != ()
0 commit comments