> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codeant.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Pli

<AccordionGroup>
  <Accordion title="END; statements should have the same indentation level as their matching PROCEDURE, SELECT, and DO statements">
    <div class="paragraph">
      <p>For better readability, \`END statements must have the same indentation level as their matching opening PROCEDURE, SELECT, and DO statements.</p>
    </div>

    <div class="paragraph">
      <p>This rule does not verify the alignment of the compound statements DO ... END; (type 1) and BEGIN ... END;. They are mostly used together with the IF and ON\` statements and are subject to different indentation rules.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0);

      do i = 0 to 9;
      if i = 0 then /* The do was forgotten here */
        put list ('Initialization...');
        put list ('i = 0');
        end; /* Non-Compliant - should be aligned with the DO statement */
      end; /* Non-Compliant - should be aligned with the PROCEDURE statement */

      /* The procedure's end seems to be missing */
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0);

      do i = 0 to 9;
      if i = 0 then do;
        put list ('Initialization...');
        put list ('i = 0');
      end; /* This end's alignment is not verified by this rule */
      end; /* Compliant */
      end; /* Compliant */
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="INONLY or NONASSIGNABLE parameters should not be written to">
    <div class="paragraph">
      <p>Parameters that are declared as "INONLY" or "NONASSIGNABLE" are flagged as non-assignable by the compiler.</p>
    </div>

    <div class="paragraph">
      <p>This rule raises an issue when a non-assignable parameter is written to.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      sum: PROC(a, b);
      dcl a fixed dec(15,2) NONASSIGNABLE;
      dcl b fixed dec(15,2) NONASSIGNABLE;
      a = a + b; /* Noncompliant */
      return (a);
      end;
      ```

      ```pli Fix theme={null}
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Parentheses should be used in factored variable declarations">
    <div class="paragraph">
      <p>When multiple variables are `DECLARE`d in a single statement, parentheses must be used around the variable list to ensure the variable attributes in the statement are applied to all the variables in the declaration. Without parentheses, the attributes are applied only to the last variable in the list.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      DECLARE X,Y FIXED BIN(15);
      ```

      ```pli Fix theme={null}
      DECLARE (X,Y) FIXED BIN(15);
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="String constants should not span multiple lines">
    <div class="paragraph">
      <p>String literals written on multiple lines should not be used, especially since the new line characters are <strong>not</strong> part of the string anyway. The concatenation operator <code>||</code> should be used instead. Moreover, if trailing comments are present, they can be automatically removed by text editors and lead to unexpected results.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      put list ('Hello,      /* Noncompliant; trailing space is not readable and may be stripped */
      world');
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      put list ('Hello, ' ||
      'world');
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="VALUE should be preferred to STATIC with INIT">
    <div class="paragraph">
      <p>Identifiers declared with <a href="https://www.ibm.com/support/knowledgecenter/en/SSY2V3_5.1.0/com.ibm.ent.pl1.zos.doc/lr/value.html">\`STATIC</a> and INIT are initialized only once and may be later modified. Modifying such an identifier will fail at runtime when a CICS application is <a href="https://www.ibm.com/docs/en/cics-ts/5.6?topic=applications-multithreading-reentrant-quasi-reentrant-threadsafe-programs">executed as reentrant</a>. It is safer to declare the value as <a href="https://www.ibm.com/support/knowledgecenter/en/SSY2V3_5.1.0/com.ibm.ent.pl1.zos.doc/lr/value.html">a named constant</a> (using the keyword VALUE) because any modification will be reported at compilation time.</p>
    </div>

    <div class="paragraph">
      <p>This rule raises an issue when an identifier is declared as STATIC with INIT or INITIAL\` and has one of the following types:</p>
    </div>

    <div class="ulist">
      <ul>
        <li>
          <p>CHARACTER/CHAR</p>
        </li>

        <li>
          <p>BINARY/BIN</p>
        </li>

        <li>
          <p>DECIMAL/DEC</p>
        </li>

        <li>
          <p>FLOAT</p>
        </li>

        <li>
          <p>POINTER/PTR</p>
        </li>

        <li>
          <p>OFFSET</p>
        </li>
      </ul>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      dcl returnCodeOk fixed bin(15) static init (00); /* Noncompliant */
      /* or */
      dcl actions char(05) init('12345') static; /* Noncompliant */
      dcl actions_in char(01);
      ....
      valid_action = (verify(action_in, actions) = 0);
      ```

      ```pli Fix theme={null}
      dcl returnCodeOk fixed bin(15) value (00);
      /* or */
      dcl actions char(05) value('12345');
      dcl actions_in char(01);
      ....
      valid_action = (verify(action_in, actions) = 0);
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Comments should not be nested">
    <div class="paragraph">
      <p>Defining a nested single-line comment within a multi-line comment invites errors. It may lead a developer to wrongly think that the lines located after the single-line comment are not part of the comment.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      /*
      This is a comment block, for which the ending tag was omitted
      It may be difficult to figure out that the following line of code is actually commented


      variable = function_call();
      /* variable contains the result, this is not allowed, as it is an attempt to create an inner comment */
      ```

      ```pli Fix theme={null}
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="The DCL abbreviation should not be used">
    <div class="paragraph">
      <p>For better readability, it is preferable to use <code>DECLARE instead of the unpronounceable DCL</code> abbreviation.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      dcl i fixed decimal init (0); /* Noncompliant */
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0); /* Compliant */
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="FIXED DECIMAL declarations should be defined with odd length">
    <div class="paragraph">
      <p>The storage of a <code>FIXED DECIMAL</code> is most efficient when you use an odd number of digits, so that the leftmost byte is fully used.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      declare total fixed dec(10);
      ```

      ```pli Fix theme={null}
      declare total fixed dec(9);
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="IF / ELSE statements should use DO ... END structures">
    <div class="paragraph">
      <p>While not technically incorrect, the omission of \`DO ... END can be misleading and may lead to the introduction of errors during maintenance.</p>
    </div>

    <div class="paragraph">
      <p>In the following example, the two commands seem to be attached to the IF statement, but only the first one is, and put list ('42!')\` will always be executed:</p>
    </div>

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0);

      if i = 42 then
      put list ('The answer is... '); /* Noncompliant */
      put list ('42!');
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0);

      if i = 42 then do;
      put list ('The answer is... ');
      put list ('42!');
      end;
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="FIXED BIN should be preferred to INT">
    <div class="paragraph">
      <p><code>fixed bin(31) type has been optimized to run faster than int especially when used in loops. For this reason, fixed bin(31) should be preferred to int</code>.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      dcl i int(2) init (0);
      do i = 1 to 20 by 1;
      ...
      end;
      ```

      ```pli Fix theme={null}
      dcl i fixed bin(31) init (0);
      do i = 1 to 20 by 1;
      ...
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Keywords should not be used as variable names">
    <div class="paragraph">
      <p>PL/I, unlike many other programming languages, does not reserve any word’s usage.</p>
    </div>

    <div class="paragraph">
      <p>This implies that it is syntaxically valid to use the keyword <code>IF</code> as variable names for instance.</p>
    </div>

    <div class="paragraph">
      <p>But doing so results in confusing code which is hard to read, especially in editors without proper PL/I syntax highlighting support.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare if fixed decimal init (42); /* Non-Compliant */

      if if = 42 then do; /* Cconfusing */
      put list ('if = 42');
      end;

      go to goto; /* Confusing */

      goto: /* Non-Compliant */
      ;
      end;
      ```

      ```pli Fix theme={null}
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="DFHRESP should be used to check EIBRESP values">
    <div class="paragraph">
      <p>Whenever a CICS command is used with a \`NOHANDE or RESP option, the default CICS exception handling is disabled. The correct approach then is to ensure that every possible exception is handled correctly directly in the code and to do this, you need to examine the RESP value or the EIBRESP field value.</p>
    </div>

    <div class="paragraph">
      <p>It is possible to compare the RESP and EIBRESP field values to hard-coded numbers or variables containing numeric values; however, this makes the code difficult to read and maintain. It is recommended to use instead the DFHRESP built-in translator function, which enables the use of the equivalent symbolic values.</p>
    </div>

    <div class="paragraph">
      <p>This rule raises an issue when the EIBRESP field is compared directly to a variable or hard-coded numeric value that is not wrapped in the DFHRESP function.</p>
    </div>

    <div class="paragraph">
      <p>This rule does not handle RESP\` values for now.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      if EIBRESP=36 then /* Noncompliant */
      end;

      if EIBRESP=MAPFAIL then /* Noncompliant */
      end;

      select (EIBRESP);
      when(36) ...;  /* Noncompliant */
      end;
      ```

      ```pli Fix theme={null}
      if EIBRESP=DFHRESP(36) then
      end;

      if EIBRESP=DFHRESP(MAPFAIL) then
      end;

      select (EIBRESP);
      when(DFHRESP(MAPFAIL)) ...;
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="SELECT statements should end with OTHERWISE statements">
    <div class="paragraph">
      <p>If every <code>WHEN test of a SELECT statement fails, an ERROR condition is raised if the OTHERWISE</code> statement is omitted. This can lead to the unexpected termination of the program.</p>
    </div>

    <div class="paragraph" />

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare i fixed decimal init (42);

      select (i); /* Non-Compliant - SELECT without OTHERWISE statement */
      when (0) put list ('i = 0');
      when (1) put list ('i = 1');
      end;

      put list ('Continuation'); /* This statement will not be executed */
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare i fixed decimal init (42);

      select (i); /* Compliant */
      when (0) put list ('i = 0');
      when (1) put list ('i = 1');
      otherwise; /* No operation */
      end;

      put list ('Continuation'); /* This statement will be executed */
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Statements should be on separate lines">
    <div class="paragraph">
      <p>Putting multiple statements on a single line lowers the code readability and makes debugging the code more complex.</p>
    </div>

    <div class="paragraph">
      <p>Unresolved directive in \<stdin> - include::\{noncompliant}\[]</p>
    </div>

    <div class="paragraph">
      <p>Write one statement per line to improve readability.</p>
    </div>

    <div class="paragraph">
      <p>Unresolved directive in \<stdin> - include::\{compliant}\[]</p>
    </div>

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare i fixed decimal init(42); put list (i); /* Noncompliant - there are two statements */
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare i fixed decimal init(42);
      put list (i);
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Variable names should comply with a naming convention">
    <div class="paragraph">
      <p>Sharing some naming conventions is a key point to make it possible for a team to efficiently collaborate. This rule allows to check that all variable names match a provided regular expression.</p>
    </div>

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare bar# fixed decimal; /* Noncompliant */
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare bar fixed decimal;  /* Compliant */
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="GO TO statements should not be used">
    <div class="paragraph">
      <p><code>goto is an unstructured control flow statement. It makes code less readable and maintainable. Structured control flow statements such as if, for, while, continue or break</code> should be used instead.</p>
    </div>

    <CodeGroup>
      ```pli Bad theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0);

      loopLabel:
      put list (i);
      i = i + 1;
      if i < 10 then go to loopLabel;  /* Noncompliant - usage of the GO TO statement */
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);
      declare i fixed decimal init (0);


      do i = 0 to 9;   /* Compliant */
      put list (i);
      end;
      end;
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Procedure names should comply with a naming convention">
    <div class="paragraph">
      <p>Shared coding conventions allow teams to collaborate efficiently. This rule checks that all function names match a provided regular expression.</p>
    </div>

    <CodeGroup>
      ```pli Bad theme={null}
      foo#: proc options(main); /* Non-Compliant */
      end;
      ```

      ```pli Fix theme={null}
      foo: proc options(main);  /* Compliant */
      end;
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>
