Solidity code linter providing security and style guide validations for smart contract development
—
Configuration loading and management system with hierarchical config resolution and rule inheritance. Solhint supports flexible configuration through various sources and formats, with support for rule extension and per-file configuration.
Loads configuration from file or searches for config files using cosmiconfig.
/**
* Loads configuration from file or searches for config files
* @param {string} configFile - Path to specific config file (optional)
* @returns {Object} Configuration object with rules and settings
* @throws {Error} If specified config file doesn't exist or contains invalid configuration
*/
function loadConfig(configFile);Usage Examples:
const { loadConfig } = require('solhint/lib/config/config-file');
// Load from default search locations
const config = loadConfig();
console.log('Rules:', config.rules);
console.log('Extends:', config.extends);
// Load specific config file
const customConfig = loadConfig('./.solhint-custom.json');
// Handle errors
try {
const config = loadConfig('./nonexistent.json');
} catch (error) {
console.error('Config loading failed:', error.message);
}Default Search Locations:
package.json (solhint property).solhint.json.solhintrc.solhintrc.json.solhintrc.yaml.solhintrc.yml.solhintrc.jssolhint.config.jsLoads configuration for a specific file with hierarchical config merging from directory structure.
/**
* Loads configuration for a specific file with hierarchical config merging
* @param {string} filePath - Path to file being linted
* @param {string} rootDir - Root directory for config search
* @param {string} explicitConfigPath - Explicit config file path (optional)
* @returns {Object} Merged configuration object
*/
function loadConfigForFile(filePath, rootDir, explicitConfigPath);Usage Examples:
const { loadConfigForFile } = require('solhint/lib/config/config-file');
// Load config for specific file with hierarchy
const fileConfig = loadConfigForFile(
'./src/contracts/Token.sol',
process.cwd()
);
// With explicit config file (bypasses hierarchy)
const explicitConfig = loadConfigForFile(
'./src/contracts/Token.sol',
process.cwd(),
'./.solhint-strict.json'
);
// Directory hierarchy example:
// /project/.solhint.json (base config)
// /project/src/.solhint.json (overrides for src)
// /project/src/contracts/.solhint.json (overrides for contracts)
// Results in merged config with contracts config taking precedenceApplies configuration inheritance via extends property with support for built-in and external configs.
/**
* Applies configuration inheritance via extends property
* @param {Object} config - Base configuration object
* @param {Function} getter - Function to resolve extended configs (optional)
* @returns {Object} Extended configuration object with merged rules
*/
function applyExtends(config, getter);Usage Examples:
const { applyExtends } = require('solhint/lib/config/config-file');
// Basic extends usage
const baseConfig = {
extends: 'solhint:recommended',
rules: {
'max-line-length': ['warn', 120] // Override recommended setting
}
};
const extendedConfig = applyExtends(baseConfig);
console.log('Final rules:', extendedConfig.rules);
// Multiple extends
const multiConfig = {
extends: ['solhint:recommended', 'solhint:all'],
rules: {
'no-console': 'off' // Disable specific rule
}
};
const finalConfig = applyExtends(multiConfig);
// Custom getter for external configs
const customGetter = (path) => {
if (path === 'my-custom-config') {
return require('./my-config.js');
}
return require(`solhint-config-${path}`);
};
const customConfig = applyExtends(
{ extends: 'my-custom-config' },
customGetter
);Built-in Configurations:
solhint:recommended - Recommended rules for most projectssolhint:all - All available rules enabledResolves and loads configuration from various sources including built-in configs, external packages, and absolute paths.
/**
* Resolves and loads configuration from various sources
* @param {string} path - Path or identifier to configuration
* @returns {Object} Configuration object
* @throws {ConfigMissingError} If configuration cannot be found
*/
function configGetter(path);Usage Examples:
const { configGetter } = require('solhint/lib/config/config-file');
// Load built-in config
const recommended = configGetter('solhint:recommended');
// Load external package config
const externalConfig = configGetter('strict'); // Loads solhint-config-strict
// Load absolute path config
const absoluteConfig = configGetter('/path/to/config.js');Validates configuration object against schema to ensure proper structure and rule definitions.
/**
* Validates configuration object against schema
* @param {Object} config - Configuration object to validate
* @throws {ValidationError} If configuration is invalid
*/
function validate(config);Usage Examples:
const { validate } = require('solhint/lib/config/config-validator');
const config = {
rules: {
'func-visibility': 'error',
'max-line-length': ['warn', 120],
'invalid-rule': 'error' // This will cause validation error
}
};
try {
validate(config);
console.log('Configuration is valid');
} catch (error) {
console.error('Validation failed:', error.message);
}{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", "^0.8.0"],
"func-visibility": "error",
"max-line-length": ["warn", 120]
},
"excludedFiles": ["contracts/test/**", "contracts/mocks/**"],
"plugins": ["prettier"]
}module.exports = {
extends: 'solhint:recommended',
rules: {
'compiler-version': ['error', '^0.8.0'],
'func-visibility': 'error',
'max-line-length': ['warn', 120]
},
excludedFiles: ['contracts/test/**', 'contracts/mocks/**']
};{
"name": "my-project",
"solhint": {
"extends": "solhint:recommended",
"rules": {
"func-visibility": "error"
}
}
}interface ConfigObject {
rules?: { [ruleId: string]: string | [string, ...any[]] };
extends?: string | string[];
excludedFiles?: string[];
plugins?: string[];
cache?: boolean;
cacheLocation?: string;
}Rules can be configured with different severity levels and options:
{
"rules": {
"func-visibility": "error", // Simple severity
"max-line-length": ["warn", 120], // Severity with options
"compiler-version": ["error", "^0.8.0"], // Severity with version constraint
"no-console": "off" // Disabled rule
}
}Severity Levels:
"error" - Causes linting to fail with exit code 1"warn" - Issues warnings but doesn't fail linting"off" or false - Disables the rule completely{
"excludedFiles": [
"contracts/test/**", // Exclude test files
"contracts/mocks/**", // Exclude mock contracts
"node_modules/**", // Exclude dependencies
"**/*.temp.sol" // Exclude temporary files
]
}{
"plugins": ["prettier", "security"],
"rules": {
"prettier/prettier": "error",
"security/no-hardcoded-secrets": "warn"
}
}Configuration files are searched and merged from root directory to file directory:
/project/.solhint.json (base configuration)/project/src/.solhint.json (src-specific overrides)/project/src/contracts/.solhint.json (contract-specific overrides)Later configurations override earlier ones, allowing for fine-grained control.
Inline configuration using comment directives:
// solhint-disable-next-line func-visibility
function test() {}
// solhint-disable max-line-length
function veryLongFunctionNameThatExceedsMaxLineLength() public pure returns (uint256) {}
// solhint-enable max-line-length
/* solhint-disable */
contract UnlintedContract {
// No rules applied here
}
/* solhint-enable */Available Directives:
solhint-disable - Disable rules from this pointsolhint-enable - Re-enable rules from this pointsolhint-disable-next-line - Disable rules for next line onlysolhint-disable-line - Disable rules for current lineconst { ConfigMissingError } = require('solhint/lib/common/errors');
try {
const config = loadConfig('./missing-config.json');
} catch (error) {
if (error instanceof ConfigMissingError) {
console.log('Config file not found, using defaults');
} else {
console.error('Config loading failed:', error.message);
}
}Install with Tessl CLI
npx tessl i tessl/npm-solhint