Skip to content

2. Suppressions, baselines and fixes ​

Three ways to deal with a finding, besides fixing the code by hand.

Fixing by hand ​

The abstract interface gets its implicit none (an interface body is a separate scoping unit: it does not inherit the module's):

fortran
abstract interface
   pure function integrand(x) result(y)
   !< A function of one real variable.
   import :: R8P
   implicit none

Suppressing one finding, with a reason ​

use mpi stays as it is: the module's names all start with mpi_, so importing them all hides nothing. An inline comment says so, and silences that rule on that line only:

fortran
use mpi ! fobis: ignore[COR040] the mpi module's names are all prefixed mpi_
console
$ fobis lint --select COR002,COR040
0 finding(s) in 10 file(s)

A suppression without a reason, or one that suppresses nothing, is itself reported.

Automatic fixes ​

Some rules know their fix. --diff shows them, --fix applies them:

console
$ fobis lint --select OBS005,OBS011,MDN021 --diff
--- a/src/romberg.f
+++ b/src/romberg.f
@@ -8,20 +8,20 @@
       H = B - A
       R(1,1) = 0.5D0*H*(F(A)+F(B))
       N = 1
-      DO 30 I = 2, 10
+      DO I = 2, 10
          H = 0.5D0*H
          S = 0.0D0
-         DO 10 K = 1, N
+         DO K = 1, N
             S = S + F(A+DBLE(2*K-1)*H)
-   10    CONTINUE
+         END DO
          R(I,1) = 0.5D0*R(I-1,1) + H*S
          N = 2*N
-         DO 20 J = 2, I
+         DO J = 2, I
             R(I,J) = R(I,J-1)
      &             + (R(I,J-1)-R(I-1,J-1))/(4.0D0**(J-1)-1.0D0)
-   20    CONTINUE
-         IF (DABS(R(I,I)-R(I-1,I-1)) .LT. TOL) GOTO 40
-   30 CONTINUE
+         END DO
+         IF (ABS(R(I,I)-R(I-1,I-1)) < TOL) GOTO 40
+      END DO
       I = 10
    40 ROMB = R(I,I)
       RETURN

Labelled DO loops become block loops (DO 30 too, although a GOTO jumps out of it: the label it jumps to is another one), DABS becomes ABS, .LT. becomes <. Chapter 5 applies them only after the tests confirmed them.

A baseline for the rest ​

An old file can have more findings than anyone will fix this week. A baseline records the current ones; from then on only new findings are reported, so the linter can run in CI today:

console
$ fobis lint --update-baseline && head -n 14 .fobis-lint-baseline.json
Baseline .fobis-lint-baseline.json: 12 finding(s) recorded
{
 "version": 1,
 "tool": "fobis lint",
 "findings": [
  {
   "rule": "COR001",
   "path": "src/romberg.f",
   "fingerprint": "9edb8cdb21af9611",
   "message": "function 'romb' has no 'implicit none'"
  },
  {
   "rule": "COR031",
   "path": "src/romberg.f",
   "fingerprint": "a34062bfd0a685a4",
console
$ fobis lint
0 finding(s) in 10 file(s), 12 hidden by the baseline

A finding is recorded by its rule, file and the text of its statement, not by its line: code added above it does not bring it back. .fobis-lint-baseline.json is read by default; commit it.

What you learned

Inline suppressions with a reason, --diff/--fix, --update-baseline. Reference: linting.

Next: 3. Reviewing a change.