 Learn all about Computer Science What Is Linting? 2025-07-04 04:23 UTC by John Caleb 1. Overview
A linter is a tool that analyzes source code to find potential problems such as syntax and logic errors, inconsistent formatting, and violations of the adopted coding style. This term is derived from lint, small bits of fiber shed by clothing, and was used in computing to describe tiny code faults.
In this tutorial, we’ll examine linting in software development, how it works, its importance, and the most common linting tools for various programming languages.
2. Why Linters Are Useful
Linters often catch issues that manual reviews miss. Without a linter, we can encounter inconsistent code formatting or logical mistakes that only become obvious during runtime or testing.
In addition, by utilizing a linter, we add a layer of automatic quality control, as linters can enforce uniform style guidelines like indentation, naming conventions, and spacing. As a result, we prevent future problems and improve our code’s readability and comprehension.
Also, linters help us cut review time while maintaining a higher level of code quality throughout our applications.
3. How Does a Linter Work?
A linter operates in several phases to evaluate source code and report any issues:

To understand the internal workings of a linter, we’ll look at a JavaScript code example and walk through how it’s processed in phases:
function greet() {
console.log(message);
var message = "Hello, world!"
}
In this example, the greet function logs a variable message before declaring it. Although variable hoisting allows JavaScript to permit this, it displays undefined instead of the “Hello, world!” string. This isn’t a syntax error, but linters are designed to detect typical semantic errors such as this one.
3.1. Parsing
A linter converts raw source code into an abstract syntax tree (AST), a structured representation of the code’s logic and syntax. An AST enables the linter to process the code’s logic, scope, expressions, and control flow rather than depend solely on text matching. It allows linting tools to detect both syntactic and logical errors.
Here’s the AST of the previous JavaScript code:
Program
|- FunctionDeclaration (id: greet)
|- Identifier (greet)
|- BlockStatement
|- ExpressionStatement
|- CallExpression
|- MemberExpression (object: console, property: log)
|- Identifier (message)
|- VariableDeclaration (kind: var)
|- VariableDeclarator
|- Identified (message)
|- Literal ("Hello, world!")
In this example, each code element corresponds to a node in the tree. The root node (Program) has a function declaration. The function’s body (BlockStatement) contains two children: an expression statement that logs a value and a variable declaration that defines the message.
Parsing enables the linter to reason about variable usage and identify errors and issues such as undefined variables, unreachable code, or incorrect function usage.
3.2. Applying Rules
After parsing the source code into an AST, the linter executes the rules step. In this phase, the linter traverses the AST and evaluates it using a set of predefined or user-configured rules.
The rules can be syntactic, semantic, and stylistic.
Syntactic rules check if the code has a proper structure. For instance, if the function keyword were absent from a function declaration in JavaScript, the linter wouldn’t build a FunctionDeclaration node and would indicate a syntactic issue immediately. Semantic rules enforce a well-defined logic, such as using a variable only after it’s defined. Finally, stylistic rules enforce formatting (proper indentation, spacing, etc.).
In our code example, two rules have been violated:
Program
|- FunctionDeclaration (id: greet)
|- Identifier (greet)
|- BlockStatement
|- ExpressionStatement
|- CallExpression
|- MemberExpression (object: console, property: log)
|- Identifier (message) # Semantic rule violation: no-use-before-define
|- VariableDeclaration (kind: var)
|- VariableDeclarator
|- Identifier (message)
|- Literal ("Hello, world!") # Stylistic rule violation: missing semicolon
The message Identifier is a child of CallExpression. However, the VariableDeclarator isn’t on its path from the root. That isn’t a syntax error but a semantic one. Similarly, there’s no semicolon after “Hello, world” which is a stylistic error. Although JavaScript automatically inserts semicolons in such cases, enabling “semi”: [“error”, “always”] in our linter configuration treats this as an error to enforce consistent style.
3.3. Reporting
After applying the rules and detecting problems, the linter enters the reporting phase and displays the summary of all the issues it has discovered in the code. An issue report usually includes the file name, line number, column, the issue nature, and a brief note detailing the problem.
Linters support various kinds of reporting documents, including text output in the console, formatted summaries in IDEs, and JSON and XML reports for CI/CD integration. This is what we get with ESLint when we apply it to our code example:
greet.js
2:15 error 'message' was used before it was defined no-use-before-define
3:37 error Missing semicolon semi
2 problems (2 errors, 0 warnings)
In this example, the report reveals two issues: the absence of a semicolon following the string “Hello, world!” and a semantic error for using the variable message before it was declared. In our ESLint configuration, we tell the linter to interpret missing semicolons as actual errors by setting the “semi”: [“error”, “always”] rule.
4. Auto Fixes
Modern linters can automatically fix certain issues using a feature called auto-fixing. However, not all issues are safe for auto-fix. Linters don’t automatically resolve logic issues such as undefined variables, unneeded function parameters, or questionable control flows. These require the insight of a developer.
In our previous example, the linter can fix a missing semicolon but it shouldn’t fix an undeclared variable.
5. Linter Configuration
We can configure linters to follow our project’s style, structure, and requirements
A linter configuration specifies which coding standards to apply, the severity of specific rules, and which files or folders to exclude from examination.
Here’s how we can customize ESLint:
{
"env": {
"browser": true,
"es2021": true
},
"extends": "eslint:recommended",
"rules": {
"no-unused-vars": "warn",
"no-console": "off",
"semi": ["error", "always"]
}
}
We create an ESLint configuration for the greet() function. Using JavaScript Object Notation, we notify ESLint that our code is designed to run in a browser and supports contemporary JavaScript syntax up to ES2021. The extends field loads a list of preset best-practice guidelines.
We set no-unneeded-vars to “warn”, which indicates unused variables but doesn’t fail the build. Then, we entirely disable no-console, which would otherwise complain about console.log() calls. We also require semicolons at the end of every statement using “semi”: [“error”, “always”].
Configuration significantly determines the effectiveness of lining. Without it, linters can generate too many irrelevant mistakes, creating frustration and leading developers to abandon the tool entirely.
In conclusion, every programming language has linting tools that detect language-specific errors and enforce best practices.
Choosing and setting the linter allows us to produce cleaner, safer, and more consistent code.
7. Conclusion
In this article, we discussed linting and how it can improve code quality.
Linting catches syntax and some logic problems, enforces coding standards, and maintains code uniformity. The post What Is Linting? first appeared on Baeldung on Computer Science.
Content mobilized by FeedBlitz RSS Services, the premium FeedBurner alternative. |