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!


sharelock

FIND/FOR/OPEN QUERY [recordname] has no NO-LOCK/EXCLUSIVE-LOCK

Rule "sharelock" gives this warning when it finds a "FIND", "FOR" or "OPEN QUERY" statement where no explicit NO-LOCK or EXCLUSIVE-LOCK is specified.

the risc:

Progress will use the default lock, which is SHARE-LOCK (unless the program is compiled using the -NL session parameter).


SHARE-LOCK is more expensive than NO-LOCK in terms of server resources. Anyway it's always better to explicitly specify the lock type and not rely on default behavior for this matter.

how to solve this:


noproparse

Proparse required but not found

Prolint is configured to use rules that require proparse.dll, but proparse.dll is not found.

Possible causes:

  • proparse is not installed. It is a separate product, available from http://www.joanju.com/proparse
  • Prolint searches for "proparse/proparse.dll" in the PROPATH. Perhaps you need to change PROPATH or move directory "proparse" into a
    directory that is listed in PROPATH.

    Not every rule requires proparse. For example, a rule that searches


  • ttnoindex

    TempTable [name] defined like [table] has no index defined.

    Rule "ttnoindex" gives this warning when it finds a DEFINE TEMPTABLE statement that is defined LIKE another table but doesn't contain the USE-INDEX statement and hasn't defined an index.

    The risc:

    If the LIKE table has a large list of indexes then the temptable will inherit all those indexes, thereby increasing the overhead.

    Known issue:

    The TempTable definition may be like another temptable or table definition that has only the indexes that are needed.

    How to solve this:

    Make a habit of specifying the exact indexes that the program will be using regardless of whether they are the same as the LIKE table.

    How to suppress these warnings:


    nobrackets

    handle:[METHODNAME] should have brackets

    Rule "nobrackets" gives this warning when it finds a handle:method statement without brackets. The following methods are watched for by this rule:

         
         hQuery:OPEN-QUERY.
         hQuery:GET-FIRST.
         hQuery:GET-NEXT.
         hQuery:GET-PREV.
         hQuery:GET-LAST.
         hQuery:CLOSE-QUERY.
    

    Each of these methods should really end with brackets, just like any other method. Other methods (not included in this list) will be reported by rule "noeffect" because methods without brackets look like properties.

    how to solve this:


    message

    use MESSAGE only in debug-mode

    Rule "message" gives this warning when it finds a MESSAGE statement, except if the MESSAGE statement is found in ADM or ADM2 includefiles or
    if the MESSAGE statement was generated by the Application Builder (like the message that says that the specified .wrx could not be found).

    the risc:

    Many frameworks are using alternative error handling functions not including the MESSAGE ... VIEW-AS ALERT-BOX statement, like dialogs with context-sensitive help or built-in logging functionality.
    In organizations where such frameworks are used, it is usually forbidden to use the MESSAGE statement and use the alternative instead; this rule helps to enforce this.


    strattrib

    wrong/no string attributes on [string]

    Rule "strattrib" gives this warning when it finds a string literal that has no string attributes or wrong string attributes.
    String attributes are used primarily by the Translation Manager. Examples of strings with attributes are: "welcome":T, "prolint/rules":U.

    NO string attributes is just that: no string attributes.
    WRONG string attributes are all string attributes except :U and :T (you will probably want to modify this, take a look at the source in prolint/rules/strattrib.p)

    the risc:

    The program is not ready for Translation Manager.

    how to solve this:


    query

    GET PREV|LAST QUERY statement used without the SCROLLING keyword in the DEFINE statement

    Rule "query" gives this warning when it finds a GET PREV or GET LAST statement for a query that was defined without the SCROLLING option. This is to warn for compatibility with Oracle dataservers: Oracle requires the SCROLLING option when you want to GET PREV or GET LAST.


    nocomment

    PROCEDURE/FUNCTION [name] is not commented

    Rule "nocomment" gives this warning when it finds an internal procedure or user-defined function which does not begin with a comment.

    PROCEDURE WhatAreWeDoingHere :
       DEFINE INPUT  PARAMETER dx AS DECIMAL NO-UNDO.
       DEFINE INPUT  PARAMETER dy AS DECIMAL NO-UNDO.
       DEFINE OUTPUT PARAMETER dz AS DECIMAL NO-UNDO.
       
       - a bunch of arcane code here -
       
    END PROCEDURE.
    

    An unmodified default UIB-generated comment is NOT accepted as a valid comment.

    the risc:


    findstate-tt

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


    Rule "findstate-tt" gives this warning when it finds a "FIND" statement without [ FIRST | LAST | NEXT | PREV | CURRENT ] and has no 'IF AMBIGUOUS' statement immediately following.


    This rule only looks at temp-tables. Database tables are inspected by rule "findstate"

    The risc:

    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. However, even in the case of searching on an Unique index, it is better coding practice to add the qualifier as it indicates to other developers what your intent is.


    unquoted

    unquoted string

    Rule "unquoted" gives this warning when it finds a string literal without quotes.

    Strings "w1" and "w2" are not quoted:

    DEFINE VARIABLE RADIO-SET-2 AS INTEGER
    VIEW-AS RADIO-SET VERTICAL
    RADIO-BUTTONS w1, 0, w2, 1, "w3", 2
    SIZE 19 BY 2 NO-UNDO.
    

    Progress will create a file named "logfile" in the current directory:

    DEFINE VARIABLE logfile AS CHARACTER INITIAL "c:\temp\errorlog.txt".
    OUTPUT TO logfile.
    

    the risc:


    substitute

    replace string concatenation by SUBSTITUTE

    Rule "substitute" gives this warning when it finds a
    concatenation of several strings. For example :

    MESSAGE "customer " + fill-in-1:screen-value + " already
    exists".

    the risc:

    A translator will only get to see the separate
    strings, e.g. "customer " and " already exists" and will
    have a hard time understanding in which context these
    two fragments are used.

    how to solve this:

    use the SUBSTITUTE() function:

    MESSAGE SUBSTITUTE("customer &1 already exists", fill-
    in-1:screen-value).

    How to suppress these warnings:


    tablename

    field [fieldname] must be qualified with tablename

    Rule "tablename" gives this warning when it finds a filedname that is not qualified with a tablename.

    FOR EACH customer :
      DISPLAY cust-num.  /* should be customer.cust-num */
    END.
    /* typo in variable: should be "name" instead "nane" */
    DEFINE VARIABLE nane AS CHARACTER NO-UNDO.
    ASSIGN 
       name = "Bill".  /* expect to assign variable, but assigns customer.name instead! */
    

    the risc:

    Humans cannot see if "cust-num" is a variable or a database fieldname. Hard to find run-time bugs can result from small typos as illustrated in the example.


    maxchar

    String constant too long for Tranman

    Rule "maxchar" gives this warning when it finds a string constant that is longer that 188 characters,
    unless the string has the :U attribute (untranslatable).

    the risc:

    "Translation Manager" can not import those long strings. It has an index on string value, and indexes in Progress are
    limited to 188 chars max.

    how to solve this:

    Cut the string constant in smaller pieces.

    implementation:
    This rule is implemented in Turbolint


    shared

    avoid SHARED on {variable|temp-table|buffer} name

    Rule "shared" gives this warning when it finds a "DEFINE" statement that contains a SHARE phrase (like SHARED, NEW SHARED, NEW GLOBAL SHARED).

    Shared objects are generally considered as "not done", especially in a non-modal application since procedures may be run in random order and in multiple instances.
    In general it is much better to avoid SHARED objects and replace them by parameters, or have those objects stored in persistent procedures and maintained by its internal procedures.

    exceptions:

    1. shared streams are allowed, because they cannot easily be replaced by parameters and because you can't get a handle to a stream object.
    2. NEW GLOBAL SHARED procedure-handles are allowed, for the purpose of running persistent super-procedures (or so-called libraries like windows.p).

    oflink

    OF used instead WHERE

    Rule "oflink" gives this warning when it finds a statement that uses OF instead WHERE, as in "EACH order OF customer".

    the risc:

    If an "OF"-join is used, you risk that Progress may select the wrong index. Especially when you modify or add indexes and recompile the source in the future.

    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(oflink)} directly before the statement.


    #
    Syndicate content