CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-solhint

Solidity code linter providing security and style guide validations for smart contract development

Pending
Overview
Eval results
Files

core-processing.mddocs/

Core Processing

Main linting functions for processing Solidity source code at different levels - from strings to files to directory patterns. These functions form the primary programmatic API for Solhint.

Capabilities

Process String

Processes Solidity source code from a string and returns linting results.

/**
 * Processes Solidity source code string and returns a Reporter with linting results
 * @param {string} inputStr - Solidity source code to lint
 * @param {Object} config - Configuration object with rules and settings (optional)
 * @param {string} fileName - Name of the file being processed (optional)
 * @returns {Reporter} Reporter instance with linting results
 */
function processStr(inputStr, config = {}, fileName = '');

Usage Examples:

const { processStr } = require('solhint');

// Basic usage with default config
const sourceCode = `
contract Example {
    function test() public {}
}`;
const report = processStr(sourceCode);
console.log('Errors:', report.errorCount);

// With custom configuration
const config = {
  rules: {
    'func-visibility': 'error',
    'compiler-version': ['error', '^0.8.0']
  }
};
const reportWithConfig = processStr(sourceCode, config, 'Example.sol');

// Check specific issues
if (reportWithConfig.errorCount > 0) {
  reportWithConfig.messages.forEach(msg => {
    console.log(`Line ${msg.line}: ${msg.message} (${msg.ruleId})`);
  });
}

Process File

Processes a single Solidity file and returns linting results with file metadata.

/**
 * Processes a single Solidity file and returns linting results
 * @param {string} file - Path to Solidity file to lint
 * @param {Object} config - Configuration object (optional, uses config resolution if not provided)
 * @param {string} rootDir - Root directory for config resolution (optional, defaults to process.cwd())
 * @param {string} explicitConfigPath - Path to explicit config file (optional)
 * @returns {Reporter} Reporter instance with linting results and file metadata
 */
function processFile(file, config, rootDir = process.cwd(), explicitConfigPath);

Usage Examples:

const { processFile } = require('solhint');

// Process with default configuration resolution
const report = processFile('./contracts/Token.sol');
console.log('File:', report.filePath);
console.log('Issues found:', report.reports.length);

// Process with explicit configuration
const customConfig = {
  rules: {
    'no-console': 'error',
    'max-line-length': ['warn', 120]
  }
};
const reportWithConfig = processFile(
  './contracts/Token.sol',
  customConfig,
  process.cwd()
);

// Process with explicit config file
const reportWithConfigFile = processFile(
  './contracts/Token.sol',
  undefined,
  process.cwd(),
  './.solhint-custom.json'
);

// Handle caching
const cachedConfig = {
  rules: { 'func-visibility': 'error' },
  cache: true,
  cacheLocation: './node_modules/.cache/solhint/.solhintcache.json'
};
const cachedReport = processFile('./contracts/Token.sol', cachedConfig);
if (cachedReport.skipped) {
  console.log('File was skipped due to cache');
}

Process Path

Processes multiple files matching a glob pattern and returns array of linting results.

/**
 * Processes multiple files matching a glob pattern
 * @param {string} pattern - Glob pattern to match Solidity files
 * @param {Object} config - Configuration object (optional)
 * @param {string} rootDir - Root directory for processing (optional, defaults to process.cwd())
 * @param {string} explicitConfigPath - Path to explicit config file (optional)
 * @returns {Array<Reporter>} Array of Reporter instances for each processed file
 */
function processPath(pattern, config, rootDir = process.cwd(), explicitConfigPath);

Usage Examples:

const { processPath } = require('solhint');

// Process all Solidity files in contracts directory
const reports = processPath('contracts/**/*.sol');
console.log(`Processed ${reports.length} files`);

// Calculate totals across all files
const totalErrors = reports.reduce((sum, report) => sum + report.errorCount, 0);
const totalWarnings = reports.reduce((sum, report) => sum + report.warningCount, 0);
console.log(`Total errors: ${totalErrors}, warnings: ${totalWarnings}`);

// Process with configuration and file exclusions
const config = {
  rules: {
    'compiler-version': ['error', '^0.8.0'],
    'no-unused-vars': 'warn'
  },
  excludedFiles: ['contracts/test/**', 'contracts/mocks/**']
};
const filteredReports = processPath('contracts/**/*.sol', config);

// Process specific patterns
const testReports = processPath('test/**/*.sol', {
  rules: {
    'foundry-test-functions': 'error',
    'no-console': 'off'
  }
});

// With explicit root directory
const libReports = processPath(
  'lib/**/*.sol',
  config,
  '/path/to/project'
);

Internal Processing Details

AST Parsing

All processing functions use the @solidity-parser/parser to parse Solidity code:

  • First attempts parsing with location and range information
  • Falls back to basic parsing if the enhanced parsing fails
  • Handles parser errors gracefully by returning them as linting errors

Configuration Resolution

  • processStr uses configuration as-is with applyExtends applied
  • processFile loads configuration via loadConfigForFile unless explicit config provided
  • processPath loads base configuration for file filtering, then per-file configs for processing

Caching System

When caching is enabled:

  • Cache is stored in node_modules/.cache/solhint/.solhintcache.json by default
  • Files are skipped if unchanged and previous results had no errors
  • Cache entries include file hash, config hash, and modification time
  • Cache is updated after successful processing without errors

Error Handling

  • Parse errors are converted to linting reports with ERROR severity
  • File system errors (missing files, permission issues) throw exceptions
  • Configuration errors throw exceptions during config loading
  • Rule execution errors are caught and reported as linting issues

Performance Considerations

  • Use processPath for batch processing as it optimizes caching across files
  • Enable caching for repeated runs on large codebases
  • Consider using explicit configuration to avoid repeated config resolution
  • Exclude test and mock files when not needed to reduce processing time

Cache Management APIs

The following APIs from solhint/lib/cache/cache-manager provide low-level cache functionality:

Read Cache

/**
 * Reads cache data from file system
 * @param {string} cachePath - Path to cache file
 * @returns {Object} Cache data object (empty object if file doesn't exist)
 */
function readCache(cachePath);

Write Cache

/**
 * Writes cache data to file system
 * @param {string} cachePath - Path to cache file
 * @param {Object} cacheData - Cache data to write
 */
function writeCache(cachePath, cacheData);

Should Lint

/**
 * Determines if a file should be linted based on cache
 * @param {string} filePath - Path to file being checked
 * @param {string} content - Current file content
 * @param {Object} config - Configuration object
 * @param {Object} cacheData - Current cache data
 * @returns {boolean} True if file should be linted
 */
function shouldLint(filePath, content, config, cacheData);

Update Cache Entry

/**
 * Updates cache entry for a file
 * @param {string} filePath - Path to file
 * @param {string} content - File content
 * @param {Object} config - Configuration object  
 * @param {Object} cacheData - Cache data to update
 */
function updateCacheEntry(filePath, content, config, cacheData);

Usage Examples:

const { readCache, writeCache, shouldLint, updateCacheEntry } = require('solhint/lib/cache/cache-manager');

// Read existing cache
const cachePath = 'node_modules/.cache/solhint/.solhintcache.json';
const cacheData = readCache(cachePath);

// Check if file needs linting
const filePath = './contracts/Token.sol';
const content = fs.readFileSync(filePath, 'utf8');
const config = { rules: { 'func-visibility': 'error' } };

if (shouldLint(filePath, content, config, cacheData)) {
  // Perform linting...
  console.log('File needs linting');
  
  // Update cache after successful linting (no errors)
  updateCacheEntry(filePath, content, config, cacheData);
  writeCache(cachePath, cacheData);
} else {
  console.log('File skipped due to cache');
}

Install with Tessl CLI

npx tessl i tessl/npm-solhint

docs

cli-interface.md

configuration-management.md

core-processing.md

index.md

output-formatting.md

result-reporting.md

rules-system.md

tile.json