|
1 | | -# Flag names mentioned in use clauses. Use type clauses and names mentioned in |
2 | | -# them are not flagged. |
3 | | -# This rule has an optional parameter Exempt_Operator_Packages: do not flag a |
4 | | -# package name in a package use clause if it refers to a package that only |
5 | | -# declares operators in its visible part. |
| 1 | +import stdlib |
6 | 2 |
|
7 | 3 | fun is_operator(s) = |
| 4 | + |" Whether given subprogram declaration of body node represents an |
| 5 | + |" operator. |
8 | 6 | s is (BasicSubpDecl | BaseSubpBody) |
9 | 7 | when s.p_defining_name().p_is_operator_name() |
10 | 8 |
|
11 | 9 | fun decls_not_only_operator(pkg) = |
12 | | - [s for s in match pkg.p_referenced_decl() |
13 | | - | p@BasePackageDecl => p.f_public_part.f_decls.children |
14 | | - | p@PackageRenamingDecl => p.p_final_renamed_package() |
15 | | - .f_public_part.f_decls.children |
16 | | - | p@GenericPackageInstantiation => p.p_designated_generic_decl() |
17 | | - .f_package_decl.f_public_part |
18 | | - .f_decls.children |
19 | | - | * => [] |
20 | | - if not is_operator(s)] |
| 10 | + |" Whether the given package name identifies a package that defines other |
| 11 | + |" symbols than operators. |
| 12 | + { |
| 13 | + val decls = match pkg.p_referenced_decl() |
| 14 | + | p@BasePackageDecl => p.f_public_part.f_decls.children |
| 15 | + | p@PackageRenamingDecl => p.p_final_renamed_package() |
| 16 | + .f_public_part.f_decls.children |
| 17 | + | p@GenericPackageInstantiation => p.p_designated_generic_decl() |
| 18 | + .f_package_decl.f_public_part |
| 19 | + .f_decls.children |
| 20 | + | * => []; |
| 21 | + not decls or |
| 22 | + stdlib.any([s for s in decls if not is_operator(s)]) |
| 23 | + } |
21 | 24 |
|
22 | 25 | @unit_check(help="use clause", category="Feature") |
23 | | -fun use_clauses(unit, exempt_operator_packages=false) = [ |
24 | | - {message: "use clause", loc: p} |
25 | | - for p in concat([use.f_packages.children |
26 | | - for use in from unit.root select UsePackageClause].to_list) |
27 | | - if (not exempt_operator_packages) or decls_not_only_operator(p) |
28 | | -] |
| 26 | +fun use_clauses(unit, exempt_operator_packages=false, allowed=[]) = |
| 27 | + |" Flag names mentioned in use clauses. Use type clauses and names mentioned in |
| 28 | + |" them are not flagged. |
| 29 | + |" This rule has two optional parameter: |
| 30 | + |" * exempt_operator_packages: If true, do not flag a package name in a |
| 31 | + |" package use clause if it refers to a package that only declares operators |
| 32 | + |" in its visible part. |
| 33 | + |" * allowed: List of fully qualified names to describe packages allowed in |
| 34 | + |" "use" clauses. If the "all_operator_packages" value is present in this |
| 35 | + |" list, all packages declaring only operators in their visible part are |
| 36 | + |" allowed. |
| 37 | + { |
| 38 | + val canonical_allowed = [s.to_lower_case for s in allowed].to_list; |
| 39 | + [ |
| 40 | + {message: "use clause", loc: p} |
| 41 | + for p in concat( |
| 42 | + [ |
| 43 | + [ |
| 44 | + c for c in use.f_packages.children |
| 45 | + if not c.p_referenced_decl()?.p_canonical_fully_qualified_name?() in canonical_allowed |
| 46 | + ].to_list |
| 47 | + for use in from unit.root select UsePackageClause |
| 48 | + ].to_list |
| 49 | + ) |
| 50 | + if not exempt_operator_packages or decls_not_only_operator(p) |
| 51 | + ] |
| 52 | + } |
0 commit comments