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!


check for vulnerability of the query bug

check for vulnerability of the query bug. The result list is written to the .srt file regardless of whether it's being used as a SCROLLING query or not.


check if each open query is closed

check if each open query is closed (the dynamic ones too). Risc: srt file growth.


functions (and ips) should not use variables in main scope

make sure that internal procedures and user-defined functions are not accessing variables that are defined in the MAIN BLOCK scope. This rule might have three different ways for suppressing warnings:

1 add a {&_proparse_ prolint-nowarn} directive to the variable definition to allow access in ip/udf

2 add a directive in the IP/UDF if it is allowed to access large-scoped variables

3 add a directive immediately before the statement that accesses a large-scoped variable


errortext

RETURN ERROR should have a string argument

Rule "errortext" gives this warning when it finds a "RETURN ERROR" statement without a string argument. For example:

/* prolint raises a warning: */
IF NOT AVAILABLE customer THEN 
   RETURN ERROR.
/* this is fine with prolint: */
IF NOT AVAILABLE customer THEN 
   RETURN ERROR "no data available".

How to suppress these warnings:

You can put the directive {&_proparse_ prolint-nowarn(errortext)} directly before
the RETURN ERROR statement. See also


ttlock

[NO-]LOCK on TEMP-TABLE|WORK-TABLE has no effect

Rule "ttlock" is part of an effort to clean up source code by eliminating useless commands.
A locking statement (NO-LOCK, EXCLUSIVE-LOCK, SHARE-LOCK) has no effect when applied to temp-table and work-tables, so perhaps it should be taken out.


def temp-table tttest no-undo 
    field x as char. 

def temp-table tttest1 no-undo 
    field y as char. 

/* All statements below will be reported by ProLint */ 
repeat preselect each tttest no-lock, each tttest1 where tttest1.y = tttest.x exclusive-lock: 

blocklabel

LEAVE/NEXT should specify a blocklabel

Rule "blocklabel" gives this warning when it finds a LEAVE or NEXT statement without a blocklabel. For example:

  DO WHILE TRUE :
     FOR EACH customer :
        FOR EACH order OF customer :
            IF order.shipped THEN DO:
               DISPLAY order.shippingdate.
               NEXT.
            END.
            ELSE
               RUN something.
        END.
     END.
  END.

In this example, Prolint will give the warning for NEXT on the 6th line.

the risc:


tableusage

TEMP-TABLE|BUFFER [name] is not used

Rule "tableusage" is a rule that identifies unused TEMP-TABLE, WORK-TABLE, and BUFFER definitions.

Notes:

The author, Igor Natanzon says:

  • Line number for the END keyword is not a reliable block indicator (
    ie. END. END. on one line). However, as each block is processed
    separately, I haven't noticed any problems yet. I suspect it should
    not be a problem because procedures, functions, and event triggers
    cannot be nested (or can they??).
  • Blocks I consider local for buffer define purpose are PROCEDURE,

sequence

CURRENT-VALUE|NEXT-VALUE [sequencename] statement used

Rule "sequence" gives this warning when it finds a CURRENT-VALUE or NEXT-VALUE statement. This is to test for Oracle compatibility:

  1. With Oracle you can't use "current-val" until you have run "next-value" at least once.
  2. The following is invalid via Oracle: "current-value(seq) = 1."

Sequence name [sequencename] has an invalid ending (_SEQ).

In Oracle, the name of a sequence can not end with "_seq"


defaultname

[name] is not a meaningful widget name

Rule "defaultname" gives this warning when it finds a widget which still has its default name, assigned by AppBuilder.


When you are using the AppBuilder and drop a new widget on a frame,
this new widget will have a default name like BUTTON-1 or FILL-IN-2. Those names are supposed to be replaced by a more
meaningful name.

the risc:

Source is difficult to understand when variables don't have meaningful names.

how to solve this:

Using AppBuilder, simply type a new name in the property sheet.

How to suppress these warnings:


obsoletenodes

[obsolete keyword] used, rewrite to [modern alternative]

Rule "obsoletenodes" gives this warning when it finds an obsolete Progress keyword in your source.

the risc:

Obsolete keywords may be removed from a future version of the 4GL compiler, although PSC is not likely to actually do that. A better reason to avoid obsolete keywords is that 4GL offers new ways to perform the same task, sometimes for better performance, sometimes for other reasons like OS-portability.

configuration:

You can configure this rule by editing file "prolint/rules/persist/obsoletenodes.d".


recid

RECID used, rewrite to ROWID

This rule is obsolete and is replaced by rule obsoletenodes.

Rule "recid" gives this warning whenever it finds
the RECID keyword in the source.

Progress supports the RECID function and RECID data type mainly for backward compatibility.
For most applications, use the ROWID function instead.

How to suppress these warnings:

You can put directive {&_proparse_ prolint-nowarn(recid)} directly before
the statement.
See also: suppress warnings.

implementation:


compiler

Compile error

Prolint tried to compile the sourcefile but the compiler failed. Prolint only works on compilable sources.

Prolint requires a subdirectory "temp" in the current directory where it will attempt to write files "prolint.lst" and "prolint.xrf".
Please make sure this directory exists.

If the "temp" directory exists, please compile the sourcefile to see if there are any compiler messages.


dotcomment

PERIOD comments a statement

Rule "dotcomment" gives this warning when it finds a
statement that begins with a period, for example:

.MESSAGE "hello"
   VIEW-AS ALERT-BOX.

Such a statement behaves like a comment (that is terminated by the next period).
So the MESSAGE in this example will never execute.

the risc:

The period is easily overlooked, and not too many people
know that it starts a comment. Prolint will raise a warning because it regards the dot (or period) as a
typo or as something that was accidently inserted,
perhaps by preprocessors.

how to solve this:


contains

CONTAINS operation used to search [buffer] (word index)

Rule "contains" gives this warning when it finds a statement that contains the CONTAINS keyword. This is to warn for compatibility with Oracle dataservers: Oracle has no word indexes.


where-udf

User Defined Function used in WHERE clause

Rule "where-udf" gives this warning when it finds a user defined funtion in a WHERE clause.

the risc:

If the user defined function accesses the database (contains FIND, FOR, QUERY) then you may get run-time error 7254 (in Progress 9) or may corrupt your database (in Progress 8). See also knowledge base articles 19561 and 20031.

how it works:

Prolint first tries to find the name of the function in your "whitelist" to see if the function must be regarded as harmless. If the name is not in the whitelist, Prolint tries to find the implementation of the function in the current compilation-unit. If the implementation is found and contains no statements that can possibly access the database, then the function is regarded as harmless. Otherwise, the function is regarded as possibly dangerous and Prolint will raise its warning.

How to suppress these warnings:


# Syndicate content