You've already forked langkit-query-language
mirror of
https://github.com/AdaCore/langkit-query-language.git
synced 2026-02-12 13:03:42 -08:00
198 lines
6.2 KiB
ReStructuredText
198 lines
6.2 KiB
ReStructuredText
===========
|
|
LKQL Checks
|
|
===========
|
|
|
|
This document presents a *florilège* of LKQL-based checks inspired on **GNATCheck** and **kp-toolkit**.
|
|
|
|
|
|
|
|
1. Deep inheritance hierarchies
|
|
===============================
|
|
|
|
LKQL Script::
|
|
|
|
selector super_types
|
|
| TypeDecl => skip it.type_def
|
|
| InterfaceTypeDef => skip it.interfaces
|
|
| RecordTypeDef => ()
|
|
| DerivedTypeDef => skip it.subtype_indication <> skip it.interfaces
|
|
| SubtypeIndication => skip it.name
|
|
| Name => rec it.referenced_decl(true)
|
|
| ParentList => skip *it.children
|
|
| * => ()
|
|
|
|
let result = query TypeDecl(any super_types(depth=3): *)
|
|
|
|
print(result)
|
|
|
|
|
|
Lists the type declarations which depth is greater or equal to 3.
|
|
|
|
`Deep inheritance hierarchyies test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/deep_inheritance>`_
|
|
|
|
|
|
2. Deep Library
|
|
===============
|
|
|
|
LKQL Script::
|
|
|
|
let targetDepth = 5
|
|
|
|
let result =
|
|
query PackageDecl (package_name: DefiningName(any children(depth=targetDepth): Name))
|
|
|
|
print(result)
|
|
|
|
|
|
Lists the package declations that have more than `targetDepth` parents.
|
|
|
|
`Deep library test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/deep_library>`_
|
|
|
|
|
|
3. Implicit Small
|
|
=================
|
|
|
|
LKQL Script::
|
|
|
|
let result =
|
|
query TypeDecl(any children: OrdinaryFixedPointDef, get_attribute("Small"): null)
|
|
|
|
print(result)
|
|
|
|
|
|
Lists the ordinary fixed point type declarations that lack an explicit representation clause
|
|
defining it's `'Small` value.
|
|
|
|
|
|
`Implicit small test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/implicit_small>`_
|
|
|
|
|
|
4. KP R517_023: Wrong value returned for unconstrained packed array formal
|
|
==========================================================================
|
|
|
|
LKQL Script::
|
|
|
|
let result = query CallExpr(
|
|
is_call(): true,
|
|
any children(depth=2): p@ParamAssoc when isFlagArg(p)
|
|
)
|
|
print(result)
|
|
|
|
fun isFlagArg(actual) =
|
|
val formal = getFormal(actual);
|
|
if formal == null
|
|
then false
|
|
else isInOutOrOut(formal) &&
|
|
isUnConstrainedArrayWithPacked(typeOfParamSpec(formal)) &&
|
|
isReprRecordComponent(argumentDecl(actual.r_expr))
|
|
|
|
fun getFormal(actual) =
|
|
val params = actual.get_params();
|
|
if params.length == 0 then null else params[1]?.parent?.parent
|
|
|
|
fun isReprRecordComponent(decl) =
|
|
decl is ComponentDecl(any parent:
|
|
TypeDecl(get_record_representation_clause(): RecordRepClause)
|
|
)
|
|
|
|
fun argumentDecl(argExpr) =
|
|
match argExpr
|
|
| DottedName => it.referenced_decl()
|
|
| * => null
|
|
|
|
fun typeOfParamSpec(spec) =
|
|
spec?.type_expr?.name?.referenced_decl()
|
|
|
|
fun isInOutOrOut(spec) =
|
|
spec?.mode is ModeOut || spec?.mode is ModeInOut
|
|
|
|
fun isUnConstrainedArrayWithPacked(decl) =
|
|
decl is TypeDecl(
|
|
type_def: ArrayTypeDef(any children(depth=6): BoxExpr),
|
|
get_attribute("Pack"): AdaNode
|
|
)
|
|
|
|
The compiler generates wrong code for the call to a subprogram with an In Out or Out
|
|
formal parameter of an unconstrained packed array type, when the actual parameter
|
|
is a component of a record subject to a representation clause.
|
|
|
|
This LKQL script lists the occurrences of the aforementioned issue.
|
|
|
|
`KP R517_023 test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/kp_R517_023>`_
|
|
|
|
|
|
5. Multiple entries in protected definitions
|
|
============================================
|
|
|
|
LKQL Script::
|
|
|
|
let result = query ProtectedDef any children EntryDecl(any prev_siblings is EntryDecl)
|
|
print(result)
|
|
|
|
Lists the entries that belong to a protected definition containing multiple entries.
|
|
The first entry of the definition will not be flagged.
|
|
|
|
`Multiple entries test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/multiple_entries>`_
|
|
|
|
|
|
6. No explicit real range
|
|
=========================
|
|
|
|
LKQL Script::
|
|
|
|
let result = query t @ *
|
|
when isRealWithoutRange(t) ||
|
|
t is SubtypeDecl(any super_types: s@_ when isRealWithoutRange(s))
|
|
print(result)
|
|
|
|
fun isRealWithoutRange(decl) =
|
|
decl is TypeDecl(type_def: RealTypeDef(no children: RangeSpec))
|
|
|
|
|
|
Lists the floating point type definitions that do not include an explicit range.
|
|
|
|
`No real range test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/no_real_range>`_
|
|
|
|
7. Parameters out of order
|
|
==========================
|
|
|
|
LKQL Script::
|
|
|
|
let result =
|
|
query p@ParamSpec(any next_siblings is sib@ParamSpec when priority(sib) > priority(p))
|
|
|
|
print(result)
|
|
|
|
fun priority(paramSpec) =
|
|
if paramSpec.default_expr != null then 0
|
|
else match paramSpec.mode
|
|
| ModeOut => 1
|
|
| ModeInOut => 2
|
|
| ModeIn => 3
|
|
| ModeDefault => 3
|
|
|
|
Flag each subprogram and entry declaration whose formal parameters are not ordered according to the following scheme:
|
|
* in and access parameters first, then in out parameters, and then out parameters;
|
|
* for in mode, parameters with default initialization expressions occur last
|
|
|
|
`Parameters out of order test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/paramters_order>`_
|
|
|
|
8. Raise predefined exception
|
|
=============================
|
|
|
|
LKQL Script::
|
|
|
|
let result = query r@RaiseStmt when isPredefinedName(r.exception_name)
|
|
|
|
print(result)
|
|
|
|
fun isPredefinedName(id) =
|
|
val name = id?.text;
|
|
name == "Program_Error" || name == "Constraint_Error" ||
|
|
name == "Numeric_Error" || name == "Storage_Error" ||
|
|
name == "Tasking_Error"
|
|
|
|
List `raise` statements that raise a predefined exception.
|
|
|
|
`Raise predefined exception test <https://github.com/geoffreycopin/langkit-query-language/tree/checker/testsuite/tests/checks/raise_builtin>`_
|