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!
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.
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.
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.
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
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.
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.
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.
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.
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?
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.
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.
Prolint does not know about classes and methods, yet. This leads to many Prolint warnings that should not be raised
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.
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.
(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