Niti: A Fast, Modern C++ Linter¶
Niti is a fast, modern, and lean linter for C++ designed to be simple, extensible, and easy to configure. It helps enforce coding standards and best practices in C++ projects.
The Problem¶
Maintaining code quality and consistency across a large C++ codebase is challenging. Many existing linters are complex to configure, slow, or not easily extensible to enforce project-specific rules. Developers need a tool that is fast, integrates seamlessly into their workflow, and can be tailored to their unique needs.
The Solution¶
Niti addresses these challenges by providing a simple, powerful, and extensible C++ linter written in Python. It uses the fast and accurate tree-sitter library for parsing C++ code and features a modular architecture that allows developers to easily create and share custom linting rules.
Key Features¶
Fast and Modern: Built on
tree-sitterfor high-performance and accurate C++ parsing.Highly Extensible: A modular rule system makes it easy to add custom rules for project-specific standards.
Simple Configuration: Configure Niti with a straightforward
.nitircYAML file or command-line options.Comprehensive Rule Set: Comes with over 50 built-in rules covering safety, modern C++, naming conventions, and more.
Developer-Friendly Workflow: Integrates smoothly with development tools and provides clear, actionable feedback.
Quick Start¶
To get started with Niti:
# Install Niti from the project root
pip install -e .
# Lint a single file
niti path/to/file.cpp
# Lint a directory
niti path/to/cpp/project/
# Show help
niti --help
Rule Suppression and Configuration¶
Niti provides flexible rule suppression mechanisms to handle legacy code, special cases, and configuration needs.
Configuration-based Rule Disabling¶
Disable rules globally via configuration file (.nitirc or niti.yaml):
rules:
# Disable specific rules completely
type-forbidden-int:
enabled: false
naming-variable-case:
enabled: false
# Change severity levels
include-order-wrong:
severity: warning # Instead of error
Important NOLINT Guidelines¶
Syntax Rules:
Case Sensitive: Only uppercase
NOLINTandNOLINTNEXTLINEworkRule Names: Use kebab-case rule names (e.g.,
type-forbidden-int,naming-variable-case)Comments Allowed: Additional text after NOLINT is ignored:
// NOLINT (legacy code)Comma Separation: Multiple rules:
// NOLINT rule-one,rule-two,rule-threeNo Spaces in Rule Lists: Use
rule-one,rule-twonotrule-one, rule-two
Scope and Precedence:
NOLINT: Affects only the specific line where the comment appears
NOLINTNEXTLINE: Affects only the immediately following line
File-level disable: Affects the entire file for specified rules
Configuration disable: Affects all files globally for specified rules
Precedence: Comment-based > File-level > Configuration-based
Discovering Available Rules¶
Before disabling rules, discover what’s available:
# See all available rules
niti --list-rules
# Run linter to see which rules are being triggered
niti --check your_project/
# Get detailed rule information
niti --check --verbose your_file.cpp
Common Rule Names:
type-forbidden-int- Forbids use of raw int typesnaming-variable-case- Enforces variable naming conventionsnaming-function-case- Enforces function naming conventionssafety-raw-pointer-param- Warns about raw pointer parameterssafety-unsafe-cast- Warns about unsafe type castsinclude-order-wrong- Enforces include statement orderingmodern-missing-const- Enforces const correctnessdoc-function-missing- Requires function documentation
Troubleshooting Rule Suppression¶
Common Issues and Solutions:
Rule name mismatch: Ensure kebab-case rule names
// ❌ Wrong: camelCase or snake_case int value = 42; // NOLINT typeForbiddenInt // ✅ Correct: kebab-case int value = 42; // NOLINT type-forbidden-int
Case sensitivity: Only uppercase NOLINT works
// ❌ Wrong int value = 42; // nolint type-forbidden-int // ✅ Correct int value = 42; // NOLINT type-forbidden-int
Spaces in rule lists: No spaces between rules
// ❌ Wrong: spaces between rules int Bad_Name = 42; // NOLINT type-forbidden-int, naming-variable-case // ✅ Correct: no spaces int Bad_Name = 42; // NOLINT type-forbidden-int,naming-variable-case
Comment-based Rule Suppression (NOLINT)¶
Niti supports flexible comment-based rule suppression using NOLINT directives.
Basic NOLINT Usage¶
Disable all rules for a line:
Disable specific rules for a line:
Disable rules for the next line:
File-level Rule Disabling¶
Disable specific rules for an entire file:
Advanced NOLINT Patterns¶
Legacy code integration examples: