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!


custom Help

When you create a custom Prolint rule you may also want to provide a Help file.

When your custom rule has id "xyz" then simply drop a file "xyz.htm" in directory "prolint/custom/help/rules".
When no custom help file is found, Prolint will try to open topic "xyz" at oehive.org.

This snippet from prolint/outputhandlers/logwin.w explains why:

  FILE-INFO:FILE-NAME = "prolint/custom/help/rules/":U + pContext + ".htm":U.
  IF FILE-INFO:FULL-PATHNAME<>? THEN
     fullpath = file-info:FULL-PATHNAME.
  ELSE
     fullpath = "http://oehive.org/prolint/rules/":U + pContext.

false positive in rules bufdbproc, bufdbfunc and bufdbmeth

Consider a statement like:

    DEFINE BUFFER bufCust FOR customer.

The rules (bufdbproc, bufdbfunc and bufdbmeth) in Prolint release 66 would see this statement and say "no buffer defined for table customer". Oops. That is stupid.

Reported by Arjen Meijer. Thanks Arjen!

Clearly a case of bad testing and I am truly sorry about it. To make up I have already fixed it and committed to the Subversion repository as revision 304.


New: Prolint release 66 is available

If you are using OpenEdge and Object Oriented ABL, then you definitely need to update Prolint to release 66. Until now Prolint did not know what a class or a method was, and would give all kinds of silly warnings.

If you are using Progress 9, you may also want to upgrade to Prolint 66 to take advantage of new rules that check if you didn't forget DEFINE BUFFER statements in the scope of internal procedures and user-defined functions. (and yes, in methods too of course). There was a long and lively discussion on PEG about this recently.


bufdbfunc

no buffer defined for table in function

rule "bufdbfunc" requires that DEFINE BUFFER statements exist for every database buffer that appears in the code for a user-defined function.

Example:

FUNCTION SomethingStupid RETURNS LOGICAL :
    IF customer.cust-name = "jurjen" THEN 
       customer.cust-name = "john".
    RETURN FALSE.
END FUNCTION.

should have its own local buffer, like for example

FUNCTION SomethingStupid RETURNS LOGICAL :
    DEFINE BUFFER customer FOR customer.
    IF customer.cust-name = "jurjen" THEN

bufdbproc

no buffer defined for table in internal procedure

rule "bufdbproc" requires that DEFINE BUFFER statements exist for every database buffer that appears in the code for an internal procedure.

Example:

PROCEDURE SomethingStupid :
    IF customer.cust-name = "jurjen" THEN 
       customer.cust-name = "john".
END PROCEDURE.

should have its own local buffer, like for example

PROCEDURE SomethingStupid :
    DEFINE BUFFER customer FOR customer.
    IF customer.cust-name = "jurjen" THEN 
       customer.cust-name = "john".
END PROCEDURE.

bufdbmeth

no buffer defined for table in method

rule "bufdbmeth" requires that DEFINE BUFFER statements exist for every database buffer that appears in the code for a method (in a class).

Example:

METHOD PUBLIC VOID SomethingStupid :
    IF customer.cust-name = "jurjen" THEN 
       customer.cust-name = "john".
END METHOD.

should have its own local buffer, like for example

METHOD PUBLIC VOID SomethingStupid :
    DEFINE BUFFER customer FOR customer.
    IF customer.cust-name = "jurjen" THEN 
       customer.cust-name = "john".
END METHOD.

false positives in rule "tablename" with inherited classes

Imagine class B inherits from class A.
Class A defines a property (or variable) foo as integer.
Class B contains a statement like
foo = 17.

Prolint does not see a definition for foo in class B so it assumes that foo is a database field, and gives a "tablename" warning because the field is not qualified with a tablename.
The solution would be a two-pass parser, but that sounds like difficult.


adecomm.pl not available in OEArchitect

The setup instruction for Prolint says you need to extract adecomm.pl (see instruction) but this pl file is apparently not shipped with the OpenEdge Architect edition of 10.1A.

reported by Glen West.


idea: configure Prolint rules by application layer

Wouldn't it be nice when different rules apply to different application layers? For example: in an OERA application, you would specify that database-access is never allowed outside the DataAccess layer.

Implementing this idea would mean that layers (or components, etc) can be recognized. Probably by namespace or some other filename-pattern. Frankly I don't really like to rely on filename conventions, but I have no other idea. Someone else?


Prolint tries to parse BMP files

When I specify a directory, and this directory contains a subdir with *.BMP images.
Wonder why because *.BMP does not seem to match any of the specified filespecs.


error reading XREF file (rules sortaccess, wholeindex)

Rules assume that the third field in a XREF file is an integer, but this is not true in OpenEdge 10: the third field may be the string "IMPLICIT". This results in a run-time error.
Affected code: rules/sortaccess.p, rules/wholeindex.p.
Testcase: try a class that inherits some other class.


many false positives when linting OOABL code

Prolint does not know about classes and methods, yet. This leads to many Prolint warnings that should not be raised


Cannot deal with source code using 10.1A shorthand syntax for dynamic buffer field value access: <DynBuffer>::<BufferFieldName>

10.1A permits to use shorthand code to get / set dynamic buffer-field values.
Something like:
hDynBuffer:BUFFER-FIELD("SomeField":U):BUFFER-VALUE

can now be written as:
hDynBuffer::BUFFER-VALUE

Prolint refuses to lint the file when it encounters this syntax and gives a "unexpected token: ::" error.


Small bug with the "Select files to lint" window and .cls files

You can drop .p and .w file in this window, but you cannot drop .cls, although you can type their path and get them linted anyway.


"wrong usage of ASSIGN..WHEN..statement" rule too restrictive

(originally issued by dlauzon)

I get this notification ("wrong usage of ASSIGN..WHEN..statement") when I use something like:

---
ASSIGN
lLogical = FALSE WHEN lLogical = ?
...
.
---

Since the variable in the WHEN is on the same line, it's evident that it uses the value of the variable as it was before the ASSIGN, it's not confounding as if I had:
ASSIGN
lLogical = ?
...
lLogical = FALSE WHEN lLogical = ?
.

It's not different then with a non-ASSIGN.
e.g.
If I have:
cSomeVar = cSomeVar + "hello".
I know that the right cSomeVar is the value of cSomeVar prior to this li


#
Syndicate content