Prolint

Prolint is a tool for automated source code review of Progress 4GL code. It reads one or more sourcefiles and examines it for bad programming practice
When you are interested Prolint, you are encouraged to subscribe to this group where you find the on-line tools to collaborate and discuss Prolint. There is a discussion forum, you can submit issues (for bugs and enhancement requests), you can modify the on-line documentation. So subscribe, and then don't forget to go to your subscription details to enable the e-mail notification!


lexcolon

block header should terminate with a COLON

Rule "lexcolon" identifies any block header that does not terminate with a colon. It checks PROCEDURE, FUNCTION, FOR, REPEAT, and DO.

Examples of such headers would be:

FOR EACH customer NO-LOCK. /* Rewrite to FOR EACH customer NO-LOCK: */ 
    DISPLAY customer. 
END. 

PROCEDURE.  /* Rewrite to PROCEDURE: */ 
   MESSAGE 'HELLO'. 
END PROCEDURE. 

This is purely an issue of style, not substance - and in some cases increases readability of the source code.


colon-t

attrib :T will trim [string]

Rule "colon-t" gives this warning when it finds a string literal that has the :T string attribute,
while the string begins or ends with whitespace. The string will be trimmed at run time.

This is most often caused by adding :T attributes to statements like:

  status = "there are " + string(inventory) + " items in inventory.".

After adding :T attributes, the source looks like

  status = "there are ":T + string(inventory) + " items in inventory.":T.

But the result looks pretty funny: there are5items in inventory.

how to solve this:


create

CREATE [tablename] table statement used in this program

This rule is for Oracle dataservers.

Rule "create" gives this warning when it finds a CREATE statement for creating a new record. The Oracle dataserver does not write the record until the end of the transaction, you have to "post" the record using VALIDATE or RELEASE if you need to read the record before the transaction ends.

For example:

  Def buffer c for customer.
  Create customer.
  Assign custnum = 100.
  /* validate customer.*/
  Find first c where custnum = 100.  /* This will fail unless the validate is uncommented*/

How to suppress these warnings:


findstate

FIND statement [name] defined without qualifier [ FIRST | LAST | NEXT | PREV | CURRENT ]


Rule "findstate" gives this warning when it finds a "FIND" statement without [ FIRST | LAST | NEXT | PREV | CURRENT ] while the WHERE clause does not appear to select a unique index, and if there is no 'IF AMBIGUOUS' statement immediately following.


This rule does not look at temp-tables: those are inspected by rule "findstate-tt".

The risc:

The WHERE clause does not contain enough fields to bracket all fields in a unique index. If the FIND statement returns more than one record an error will occur when an attempt to access the record is made. Also, if not already searching on an Unique index, without the qualifier the PROGRESS engine will look to see if there is another record that matches the criteria increasing the search time.


fnusage

Function name() [is prototyped but] not called in current program

Rule "fnusage" gives this warning when it finds a function or function-prototype that is never called. The function can be removed from the
source (but before you do, check if the function is not called
dynamically because dynamic calls are invisible to Prolint).


runargs

run-time arguments in RUN statement

Rule "runargs" gives this warning when it finds a run
statement with run-time arguments.

the risc:

The program will not be able to execute when it gets
deployed to a site with only a runtime license.

How to resolve this:

It is often just a typo, some common examples are:

  1. lost count of parentheses. The extra parens are
    interpreted as run-time parameters:

    RUN something ("","")).
  2. forgot to put a period at the end of the line. The
    next line (up to the period) is a runtime argument.

    RUN something ("","")
    a = b + c.

How to suppress these warnings:


nameconv

VARIABLE .... should start with "..."

Rule "nameconv" looks at the names of variables (and other names like parameters, temptables and procedures) to check
for naming conventions.

How to customize this rule:
Since naming conventions are different in every organization, you
will probably want to customize this rule. To do so you only have to
override procedure "prolint/rules/namecheck.p":

Do not change procedure "prolint/rules/namecheck.p", because your changes will
be overwritten when you upgrade Prolint. Instead, copy


sortaccess

SORT-ACCESS found in xref on table [tablename]

Rule "sortaccess" scans the XREF file and gives this warning when it finds "SORT-ACCESS".


This happens when you use the BY option in a query, while the specified
BY order is such that Progress can not select an existing index that completely fits. This means that Progress will
have to sort the result-set "on the fly" before it presents the results to the program.

the risc:

Sorting is noticeable slow if the result-set contains many records.

how to solve this:


nowhere

no WHERE-clause on table [buffername]

Rule "nowhere" gives this warning when it finds a "FOR", "FIND" or "OPEN QUERY" statement without a WHERE-clause.
In this case Prolint should also give a "wholeindex" warning.

the risc:

Progress may fetch too many records from the table, resulting in bad performance.

how to solve this:

Rewrite the statement so that it contains a WHERE-clause.

How to suppress these warnings:

You can put directive {&_proparse_ prolint-nowarn(nowhere)} directly before the statement.


wholeindex

WHOLE-INDEX found in xref on table [tablename]

Rule "wholeindex" scans the XREF file and gives this warning when it finds "WHOLE-INDEX".

This happens when you did not specify a WHERE-clause in your query, or a WHERE-clause with fields that
did not make it possible for Progress to set good index brackets.

The result can be that all records in [tablename] must be fetched and evaluated to check the WHERE-criteria. This is
bad for performance if there are many records in the table.

WHOLE-INDEX is not always slow. In the following example, Progress will report WHOLE-INDEX on the "FIND NEXT"
statement only because there is no WHERE-clause specified:

FIND customer WHERE customer.cust-num = 5 NO-LOCK NO-ERROR.
IF AVAILABLE customer THEN
   FIND NEXT customer NO-LOCK NO-ERROR.

In this particular example the FIND NEXT statement will perform pretty good despite the WHOLE-INDEX warning.


varusage

Variable usage

Rule "varusage" tests for two different events:

  • variable [identifier] is never accessed
  • variable [identifier] in procedure [procname] hides object in program scope

variable [identifier] is never accessed

This means your program defines a variable and perhaps assigns a value to that variable,
but the value of that variable is never accessed. It does not necessarily mean that the variable
itself appears nowhere in the source.

Let's have a look at a small example program:

DEFINE VARIABLE var_1 AS DECIMAL NO-UNDO.
DEFINE VARIABLE var_2 AS DECIMAL NO-UNDO.
DEFINE VARIABLE var_3 AS DECIMAL NO-UNDO.
  
var_1 = SQRT(var_2 * var_2 + var_3 * var_3).

In this example, variable var_1 is never accessed.
It has a value, but this value is never used for output or assignment to another field/variable. It may be a left-over from a piece of obsolete code that was
supposed to be deleted.

the risc:


groupassign

Possibly group ASSIGN with line ...

Rule "groupassign" gives this warning when it finds several ASSIGN
statements that could have been grouped together into one single
ASSIGN statement.

Notes:

Possible issues with this rule that may need to be fixed or not:

  • You can't have call a UDF an assign after writing to a key field.
  • Sometimes a large assign statement is split on purpose, because there is a compiler limit for the number of characters in a single statement.
  • It could be argued that intentional ASSIGN splits should all use the ASSIGN keyword. Then a variation of the rule could just report on cases where the ASSIGN keyword isn't used.

runname

progname in RUN-statement is not UNIX-compatible

Rule "runname" gives this warning when it finds a "RUN program" statement where the name of the program
contains backslashes instead of forwardslashes or when the name contains uppercase characters.

Prolint also looks at RUN VALUE(expression) statements, but then it can only raise the warning if the expression
contains one or more string literals, and one of these strings contains backslashes or uppercase characters.

RUN-statement does not end with period

Prolint performs this extra test while it is running rule "runname". Every statement has to end in a period, but
when running on a Provision license it is sometimes possible to have a RUN statement that doesn't end with a period.
Such a program won't work when deployed to a site with a runtime license.

the risc:


prolint

File not found

Prolint did not find the file you wanted to lint.

Prolint is installed more than once

Prolint found more than one directory where Prolint is installed. The list of directories where Prolint is installed, is in registry
"HKEY_CURRENT_USER/SOFTWARE/prolint" key "found_in"


matches

MATCHES statement used in this program

Rule "matches" gives this warning when it finds a MATCHES keyword.

the risc:

MATCHES is generally bad for indexing.

How to suppress these warnings:

You can put directive {&_proparse_ prolint-nowarn(matches)} directly before
the the statement that contains the MATCHES keyword.
See also: suppress warnings.


#
Syndicate content