A comprehensive CFML linter built on Lucee's native AST parser. This module provides static analysis for CFML code, replicating and extending the functionality of CFLint with a more modern, extensible architecture. It is intended to be used as a module for lucli.
- AST-Based Analysis: Uses Lucee's built-in AST parser for accurate code analysis
- Extensible Rule System: Easy to add new rules by extending the BaseRule class
- Configurable: JSON-based configuration for enabling/disabling rules and setting parameters
- Multiple Output Formats: Support for text, JSON, and XML output
- Rule Categories: Rules organized by groups (Security, BugProne, Naming, etc.)
- CFLint Compatibility: Implements many CFLint rules with the same rule codes
- Install the module via lucli:
lucli install lint - Create a
cflinter.jsonconfiguration file in your project root - Run the linter on your CFML files:
lucli lint path/to/your/file.cfm --format=text
The linter is built with a modular architecture:
- CFMLLinter: Main orchestration class that manages rules and executes linting
- ASTDomHelper: Enhanced AST traversal and querying utilities
- BaseRule: Abstract base class for all linting rules
- LintResult: Data structure for individual linting violations
- RuleConfiguration: Configuration management system
Rules extend the BaseRule class and implement a check() method:
component extends="../BaseRule" {
function initRuleProperties() {
variables.ruleCode = "AVOID_USING_CFDUMP_TAG";
variables.ruleName = "CFDumpChecker";
variables.description = "Avoid use of cfdump tags";
variables.severity = "WARNING";
variables.message = "Avoid leaving <cfdump> tags in committed code";
variables.group = "BadPractice";
}
function check(required struct node, required any helper, string fileName = "") {
var results = [];
var dumpTags = helper.getCFMLTagsByName("dump");
for (var tag in dumpTags) {
results.append(
createResultFromNode(
message = variables.message,
node = tag,
fileName = arguments.fileName
)
);
}
return results;
}
}Rules live under lib/rules/ and can be added via linter.addRule(...):
- AvoidUsingCFAbortTagRule.cfc
- AvoidUsingCFDumpTagRule.cfc
- AvoidUsingCreateObjectRule.cfc
- AvoidUsingSQL.cfc
- ExcessiveFunctionLengthRule.cfc
- FunctionHintMissingRule.cfc
- GlobalVarRule.cfc
- MissingVarRule.cfc
- QueryParamRule.cfc
- VariableNameChecker.cfc
- AVOID_USING_CFDUMP_TAG: Detects
<cfdump>tags that shouldn't be in production code - AVOID_USING_CFABORT_TAG: Detects
<cfabort>tags that shouldn't be in production code
- VAR_INVALID_NAME: Validates variable naming conventions (camelCase, length, etc.)
Create a cflinter.json file to configure the linter:
{
"global": {
"outputFormat": "text",
"showRuleNames": true,
"exitOnError": false,
"maxIssues": 0
},
"rules": {
"AVOID_USING_CFDUMP_TAG": {
"enabled": true
},
"VAR_INVALID_NAME": {
"enabled": true,
"parameters": {
"case": "camelCase",
"minLength": 3,
"maxLength": 20,
"maxWords": 4
}
}
}
}Rules that catch potential bugs and logic errors
Rules that identify potential security vulnerabilities
Rules that enforce coding best practices
Rules for code formatting and style consistency
Rules for consistent naming conventions
Rules that encourage modern CFML syntax
Rules that identify overly complex code
- Create a new CFC in
/lib/rules/extendingBaseRule - Implement the
initRuleProperties()andcheck()methods - Register the rule by calling
linter.addRule(...)wherever you bootstrap the linter - Add configuration options if needed
CFML Linter Results
====================
Total issues: 2
Errors: 0, Warnings: 1, Info: 1
WARNING - test_bad.cfm (line 2): [AVOID_USING_CFDUMP_TAG] Avoid leaving <cfdump> tags
INFO - test_bad.cfm (line 1): [VAR_INVALID_NAME] Variable x should be longer than 3 characters
{
"summary": {
"total": 2,
"errors": 0,
"warnings": 1,
"info": 1
},
"results": [...]
}<lintResults>
<summary>
<total>2</total>
<errors>0</errors>
<warnings>1</warnings>
<info>1</info>
</summary>
<issues>...</issues>
</lintResults>The module includes test files to verify functionality:
test_bad.cfm: Contains multiple linting violationstest_good.cfm: Clean code with no violations
- Automatic rule discovery and loading
- More CFLint rule implementations
- Integration with CI/CD systems
- IDE plugins and integrations
- Performance optimizations for large codebases
To contribute new rules or improvements:
- Follow the existing rule pattern in
/lib/rules/ - Add comprehensive tests
- Update configuration examples
- Document the new rule in this README
This module was created as an extensible alternative to CFLint, leveraging Lucee's native AST parsing capabilities for better accuracy and performance.