Create new rules

Each rule is a non-persistent procedure located in directory prolint/rules. A rule will be invoked by prolint.p if it is listed in file prolint/rules/rules.d.

Supporting files

file prolint/rules/rules.d

An easy way to insert a new record in this file, is to run dialog
prolint/core/dnewrule.w.

This dialog can be invoked from the Prolint Desktop window.

The file contains the following fields per record:

  1. rule_id (string)

    must be unique, not too long, and identical to the filename of the rule procedure.

  2. default severity (integer)

    indicates how bad it is when a sourcefile contains a violation against this rule.

    ranging from 0 (=not so bad) to 9 (=critical)

  3. needproparse (logical)

    yes if the rule needs proparse.dll to parse the sourcefile

  4. needlisting (logical)

    yes if the rule needs the outputfile from "COMPILE ... LISTING listingfile"

  5. needxref (logical)

    yes if the rule needs the outputfile from "COMPILE ... XREF xreffile"

  6. needprocedurelist (logical)

    yes if the rule needs to work on a list of all procedures and functions found in the sourcefile. If yes, then prolint.p will prepare this list in a temp-table.

  7. ignoreUIB (logical)

    yes if you want the rule to suppress warnings from statements in UIB/AppBuilder-generated code.

  8. description (string)

    a oneliner describing the rule, to be displayed in the configuration window

  9. category (string)

    if category is blank or missing, then "Custom" will be assigned

Set as many logicals to "no" as possible, this saves performance when the end-user doesn't run many rules.

help for end-users

Each rule should have help.
For standard rules (rules that are deployed with Prolint) these are topics at oehive.org. Simply create a book page as child of oehive.org/prolint/rules and it will work.
For custom rules (that you keep privately) you can create a .htm file in directory "prolint/custom/help/rules", see custom help for more info.

Test-scenarios, regression testing

Run prolint/launch/test.p often, to see if rules behave as expected.

See topic "regression testing" for more details.

It is often convenient to write test-cases in directory prolint/regrtest before starting to program your new rule, so you have immediate feedback while programming.
If you add test-cases please send them to me so they are included in the next Prolint release.

The rule procedure

File "prolint/rules/_template.p is a template for a new rule. You can use it as a starting point, if you don't want to start from scratch.

Each rule needs a couple of input parameters, which are defined by {prolint/core/ruleparams.i}.

I hope these parameters don't need introduction, although parameter "pragma_number" may be a stranger:

Pragmas are used for suppressing warnings. If the sourcefile contains a directive like {&_proparse prolint-nowarn(rule_id)}, then every node in the statement following the
directive will get an attribute. The identifier of the attribute is an integer named "pragma_number", the value of the attribute is 1 (to indicate that the attribute is "set").
Each rule_id has its own unique pragma_number. The procedures for searching through proparse nodes will skip each node where this pragma-attribute is set.

When the rule finds a statement or a situation where it wants to raise a warning about, you should run procedure PublishResult.


Procedure PublishResult is implemented in prolint/core/lintsuper.p which is
a super-procedure to every rule.


You should not
"publish" the warning directly to the outputhandlers using PUBLISH "Prolint_AddResult", because if you do you miss the extra functionality that lintsuper.p adds to it.

Searching nodes in the parsed source tree.

There are basically two ways to query nodes in the tree created by proparse:

  • using the recursive procedure searchNodeTree (implemented in lintsuper.p). This procedure is, for most cases, too slow.
  • using the proparse-queries implemented in procedure searchNodeQueries (in lintsuper.p).

Both procedures have identical parameter signatures, so they can be exchanged at any time - just pick the fastest one. Alternatively you can run
searchNode (also in lintsuper.p) which will choose to run either searchNodeTree or searchNodeQueries for you.

Parameters for searchNode* procedures:

  1. input startnode (integer)

    proparse node, the search will be limited to children (and grandchildren etc) of this node

  2. input callback (character)

    name of an internal procedure in the rule procedure. This procedure will be called when a matching node is found, but nodes with the pragma_number attribute are automatically skipped.

  3. input NodeTypesToInspect (character)

    comma-separated list of nodetypes to search for in/under startnode.

Progress 8-9 compatibility issues

Prolint release 63 runs in Progress 8 and in Progress 9. Prolint release 64 (and up) does not run in Progress 8 anymore.