Skip to content

Linting

Catching stylistic and problematic behaviour

Stylistic Problems

lint

Style

Flag suspicious usage in the source code.

c
int res = x - 1 << n + 1
  • Common Footguns
  • Operator precedense
  • Not awaiting futures/promises
  • Stylistic violations
text
> clang -Wall example.c

angry.c:2:17: warning: operator '<<' has lower precedence than '-'; '-' will be evaluated first [-Wshift-op-parentheses]
    2 |     int res = x - 1 << n + 1;
      |               ~~^~~ ~~
angry.c:2:17: note: place parentheses around the '-' expression to silence this warning
    2 |     int res = x - 1 << n + 1;
      |                 ^
      |               (    )
angry.c:2:26: warning: operator '<<' has lower precedence than '+'; '+' will be evaluated first [-Wshift-op-parentheses]
    2 |     int res = x - 1 << n + 1;
      |                     ~~ ~~^~~
angry.c:2:26: note: place parentheses around the '+' expression to silence this warning
    2 |     int res = x - 1 << n + 1;
      |                          ^
      |                        (    )

Linters, named after the historic program lint, are a series of tools which finds problematic, suspicious or unwarranted code in the codebase.

This can be ambiguous use operators such as [left-side snippet] which clang catches with [right-side snippet]

Linters can be run as part of the CI/CD pipeline, ensuring they are always run and submitted code is up to standard.

Not all linters are created equal, some might be more stylistic and opinionated than others. Some stylistic choices have also gone out of fashion. Good linters should have good defaults though.

Some linters are more akin to static analyzers while others more style enforcers.

It can be hard to integrate if your codebase already violates a lot the lints.

In the that case disable most of the lints and re-enable them over time, the bring the codebase up to the full rule set, or 'allow' single locations to violate the lint using annotations.

Formatters

Popularized by gofmt

Style
go
// (indenting using spaces)
func fib(n int) int {
  if n<=1 {
      return n;
  }
  a := 0;
  b := 1;
  for i := 2; i<=n; i++ {
    b = a;
    a = b+1;
  }
  return a
}
go
// (indenting using tabs)
func fib(n int) int {
	if n <= 1 {
		return n
	}
	a := 0
	b := 1
	for i := 2; i <= n; i++ {
		b = a
		a = b + 1
	}
	return a
}

Popularized by gofmt since the inclusion of official toolchain, but formatters exist for various languages (black, prettier clangformat, etc.) These tools simply take source code and reformats it. While somewhat benign, the ability to automate and enforce a format for a codebase is powerful, as it ensures it does not fall into a mix of different styles.

The given style does not matter, but the consistency of the codebase and preferably consistency within a language.

It should be evident that a consistent format improves readability by having programming flow have clear and similar visual structures.

Formatters can also check that the code conforms to the style guide, and thus be run in CI/CD and in git-hooks to ensure all committed code is formatted correctly.