Documentation
¶
Overview ¶
Package whitespace provides linting rules for whitespace and formatting issues.
This package includes 6 whitespace-related rules (L001-L005, L010) that enforce consistent whitespace usage, indentation, and line formatting in SQL code.
Rules in this Package ¶
L001: Trailing Whitespace (auto-fix)
- Detects and removes unnecessary trailing spaces or tabs at line ends
- Severity: Warning
- Common issue: Editor artifacts, copy-paste problems
L002: Mixed Indentation (auto-fix)
- Enforces consistent use of tabs or spaces for indentation
- Converts all indentation to spaces (4 spaces per tab)
- Severity: Error
- Common issue: Multiple developers with different editor settings
L003: Consecutive Blank Lines (auto-fix)
- Limits consecutive blank lines to a configurable maximum
- Default: Maximum 1 blank line between statements
- Severity: Warning
- Common issue: Excessive vertical spacing reducing code density
L004: Indentation Depth (no auto-fix)
- Warns about excessive indentation depth indicating complex queries
- Configurable maximum depth (default: 4 levels)
- Severity: Warning
- Common issue: Deeply nested subqueries needing refactoring
L005: Line Length (no auto-fix)
- Enforces maximum line length for readability
- Configurable maximum (default: 100 characters)
- Skips comment-only lines
- Severity: Info
- Common issue: Long lines hard to read in code reviews
L010: Redundant Whitespace (auto-fix)
- Removes multiple consecutive spaces (preserves indentation and strings)
- Severity: Info
- Common issue: Inconsistent spacing between SQL keywords
Usage Examples ¶
Using trailing whitespace rule:
import "github.com/ajitpratap0/GoSQLX/pkg/linter/rules/whitespace"
rule := whitespace.NewTrailingWhitespaceRule()
violations, err := rule.Check(ctx)
if len(violations) > 0 {
fixed, _ := rule.Fix(sql, violations)
// Use fixed SQL
}
Using mixed indentation rule:
rule := whitespace.NewMixedIndentationRule() violations, _ := rule.Check(ctx) // Converts all tabs to 4 spaces fixed, _ := rule.Fix(sql, violations)
Using consecutive blank lines with custom limit:
rule := whitespace.NewConsecutiveBlankLinesRule(2) // Allow max 2 blank lines violations, _ := rule.Check(ctx) fixed, _ := rule.Fix(sql, violations)
Using indentation depth with custom settings:
rule := whitespace.NewIndentationDepthRule(5, 4) // Max 5 levels, 4 spaces per level violations, _ := rule.Check(ctx) // No auto-fix available - violations indicate refactoring needed
Using line length with custom maximum:
rule := whitespace.NewLongLinesRule(120) // Max 120 characters violations, _ := rule.Check(ctx) // No auto-fix available - requires manual line breaking
Using redundant whitespace rule:
rule := whitespace.NewRedundantWhitespaceRule() violations, _ := rule.Check(ctx) fixed, _ := rule.Fix(sql, violations) // Multiple spaces become single space
Auto-Fix Behavior ¶
Four rules support auto-fixing (L001, L002, L003, L010):
L001 (Trailing Whitespace):
- Strips trailing spaces and tabs from each line
- Preserves line content and newlines
- Safe to apply without review
L002 (Mixed Indentation):
- Converts tabs to 4 spaces in leading whitespace only
- Preserves tabs inside SQL strings and comments
- Should be reviewed if project uses tabs intentionally
L003 (Consecutive Blank Lines):
- Reduces consecutive blank lines to configured maximum
- Trims excess blank lines at file end
- Safe to apply without review
L010 (Redundant Whitespace):
- Reduces 2+ consecutive spaces to single space
- Preserves leading indentation
- Preserves spaces inside string literals
- Safe to apply without review
Rules without auto-fix (L004, L005) require manual refactoring or line breaking.
Configuration Recommendations ¶
Production environments:
whitespace.NewTrailingWhitespaceRule() // Always enable whitespace.NewMixedIndentationRule() // Always enable whitespace.NewConsecutiveBlankLinesRule(1) // 1 blank line max whitespace.NewIndentationDepthRule(4, 4) // Warn at 4 levels whitespace.NewLongLinesRule(100) // 100 char limit whitespace.NewRedundantWhitespaceRule() // Always enable
Strict style enforcement:
whitespace.NewTrailingWhitespaceRule() // Error on trailing whitespace whitespace.NewMixedIndentationRule() // Error on mixed indentation whitespace.NewConsecutiveBlankLinesRule(1) // Max 1 blank line whitespace.NewIndentationDepthRule(3, 4) // Warn at 3 levels (stricter) whitespace.NewLongLinesRule(80) // 80 char limit (stricter) whitespace.NewRedundantWhitespaceRule() // Clean up spacing
Relaxed style (legacy code):
whitespace.NewTrailingWhitespaceRule() // Still remove trailing whitespace // Skip L002 if tabs are intentional whitespace.NewConsecutiveBlankLinesRule(2) // Allow 2 blank lines whitespace.NewIndentationDepthRule(6, 4) // Warn only at 6 levels whitespace.NewLongLinesRule(120) // 120 char limit // Skip L010 if varied spacing is intentional
Performance Characteristics ¶
All whitespace rules are text-based and do not require tokenization or parsing. They operate on line-by-line scanning with O(n) complexity where n is line count.
Typical performance (lines per second):
- L001, L002, L003, L010: 100,000+ lines/sec
- L004: 80,000+ lines/sec (includes depth calculation)
- L005: 100,000+ lines/sec
Auto-fix operations add minimal overhead (<10% slowdown).
Thread Safety ¶
All rule types in this package are stateless and thread-safe. Rule instances can be shared across goroutines safely.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ConsecutiveBlankLinesRule ¶
ConsecutiveBlankLinesRule (L003) detects and fixes excessive consecutive blank lines.
Excessive blank lines reduce code density and make it harder to view complete queries on screen. This rule enforces a configurable maximum number of consecutive blank lines, improving readability without eliminating vertical spacing entirely.
Rule ID: L003 Severity: Warning Auto-fix: Supported
Example violation (maxConsecutive=1):
SELECT * FROM users WHERE active = true <- Two blank lines above (violation)
Fixed output:
SELECT * FROM users WHERE active = true <- Single blank line
The rule also removes excessive blank lines at the end of files.
func NewConsecutiveBlankLinesRule ¶
func NewConsecutiveBlankLinesRule(maxConsecutive int) *ConsecutiveBlankLinesRule
NewConsecutiveBlankLinesRule creates a new L003 rule instance.
Parameters:
- maxConsecutive: Maximum number of consecutive blank lines allowed (minimum 1)
If maxConsecutive is less than 1, defaults to 1.
Returns a configured ConsecutiveBlankLinesRule ready for use with the linter.
func (*ConsecutiveBlankLinesRule) Check ¶
Check performs the consecutive blank lines check on SQL content.
Scans through lines tracking consecutive blank lines. Reports violations when consecutive blank count exceeds maxConsecutive. Also checks for excessive blank lines at file end.
Returns a slice of violations (one per sequence of excessive blank lines) and nil error.
func (*ConsecutiveBlankLinesRule) Fix ¶
func (r *ConsecutiveBlankLinesRule) Fix(content string, violations []linter.Violation) (string, error)
Fix removes excess consecutive blank lines from SQL content.
Processes content line by line, preserving up to maxConsecutive blank lines in any sequence. Additional blank lines beyond the limit are removed. Also trims excess trailing blank lines at file end.
Returns the fixed content with consecutive blank lines reduced to maximum, and nil error.
type IndentationDepthRule ¶
IndentationDepthRule (L004) detects excessive indentation depth indicating overly complex query structure.
Deep nesting in SQL queries often indicates complex subqueries that may benefit from refactoring into CTEs, views, or application-level logic. This rule helps identify queries that may be hard to understand and maintain.
Rule ID: L004 Severity: Warning Auto-fix: Not supported (requires query restructuring)
Example violation (maxDepth=4, indentSize=4):
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM (
SELECT * FROM deep_table <- 5 levels deep (violation)
This rule calculates indentation depth by dividing total leading whitespace by indentSize, treating tabs as indentSize spaces.
func NewIndentationDepthRule ¶
func NewIndentationDepthRule(maxDepth int, indentSize int) *IndentationDepthRule
NewIndentationDepthRule creates a new L004 rule instance.
Parameters:
- maxDepth: Maximum indentation depth allowed (minimum 1, default 4)
- indentSize: Number of spaces per indentation level (minimum 1, default 4)
Tabs are counted as indentSize spaces. If parameters are less than 1, defaults are applied.
Returns a configured IndentationDepthRule ready for use with the linter.
func (*IndentationDepthRule) Check ¶
Check performs the indentation depth check on SQL content.
Calculates the indentation depth of each non-empty line by counting leading whitespace (tabs converted to indentSize spaces) and dividing by indentSize. Reports violations for lines exceeding maxDepth.
Empty lines are skipped as they don't contribute to query complexity.
Returns a slice of violations (one per line exceeding maximum depth) and nil error.
func (*IndentationDepthRule) Fix ¶
Fix is not supported for this rule as it requires semantic query restructuring.
Reducing indentation depth requires understanding query logic and potentially:
- Converting nested subqueries to CTEs
- Breaking complex queries into views
- Simplifying join conditions
These transformations require human judgment and cannot be automated safely.
Returns the content unchanged with nil error.
type LongLinesRule ¶
LongLinesRule (L005) detects lines exceeding a configurable maximum length.
Long lines reduce readability, especially in code reviews, side-by-side diffs, and terminal environments. This rule enforces a maximum line length to improve readability across different viewing contexts.
Rule ID: L005 Severity: Info Auto-fix: Not supported (requires semantic understanding)
Example violation (maxLength=80):
SELECT user_id, username, email, created_at, updated_at, last_login FROM users WHERE active = true <- 95 chars (violation)
The rule skips comment-only lines as they often contain documentation or URLs that shouldn't be broken. Lines with trailing whitespace are measured including the whitespace.
func NewLongLinesRule ¶
func NewLongLinesRule(maxLength int) *LongLinesRule
NewLongLinesRule creates a new L005 rule instance.
Parameters:
- maxLength: Maximum line length in characters (minimum 1, default 100)
If maxLength is 0 or negative, defaults to 100 characters.
Returns a configured LongLinesRule ready for use with the linter.
func (*LongLinesRule) Check ¶
Check performs the long lines check on SQL content.
Measures each line's length and reports violations for lines exceeding MaxLength. Empty lines and comment-only lines (starting with -- or /*) are skipped.
The violation column points to the position just after MaxLength to indicate where the line becomes too long.
Returns a slice of violations (one per line exceeding maximum length) and nil error.
func (*LongLinesRule) Fix ¶
Fix is not supported for this rule as it requires semantic understanding.
Breaking long lines requires understanding:
- SQL clause boundaries (WHERE, AND, OR, etc.)
- String literal boundaries
- Appropriate indentation for continuation
- Logical grouping of conditions
These decisions require human judgment about readability and cannot be automated safely without risk of creating worse formatting.
Returns the content unchanged with nil error.
type MixedIndentationRule ¶
MixedIndentationRule (L002) detects and fixes inconsistent use of tabs and spaces for indentation within a file.
Mixed indentation causes display issues across different editors and environments where tab width settings vary. This rule enforces consistent indentation by detecting both line-level mixing (tabs and spaces on the same line) and file-level inconsistency (some lines using tabs, others using spaces).
Rule ID: L002 Severity: Error Auto-fix: Supported (converts all tabs to 4 spaces)
Example violations:
SELECT * <- Uses spaces FROM users <- Uses spaces WHERE active <- Uses tab
Fixed output (all spaces):
SELECT *
FROM users
WHERE active
The auto-fix converts all leading tabs to 4 spaces, preserving tabs that appear inside SQL strings or after non-whitespace characters.
func NewMixedIndentationRule ¶
func NewMixedIndentationRule() *MixedIndentationRule
NewMixedIndentationRule creates a new L002 rule instance.
The rule detects two types of violations:
- Line-level: Tabs and spaces mixed on the same line's indentation
- File-level: Different lines using different indentation styles
Auto-fix converts all indentation to spaces (4 spaces per tab).
Returns a configured MixedIndentationRule ready for use with the linter.
func (*MixedIndentationRule) Check ¶
Check performs the mixed indentation check on SQL content.
The check works in two phases:
- Detects lines with both tabs and spaces in leading whitespace
- Tracks first indentation type seen and reports inconsistency with that style
Only leading whitespace (indentation) is checked; tabs and spaces after content are not considered violations.
Returns a slice of violations (one per inconsistent line) and nil error.
func (*MixedIndentationRule) Fix ¶
Fix converts all indentation to spaces (4 spaces per tab).
Processes each line by replacing tabs with 4 spaces in the leading whitespace only. Tabs that appear after non-whitespace content (e.g., inside string literals or after SQL keywords) are preserved unchanged.
This is a safe, idempotent transformation that doesn't affect SQL semantics.
Returns the fixed content with consistent space-based indentation, and nil error.
type RedundantWhitespaceRule ¶
RedundantWhitespaceRule (L010) detects and removes multiple consecutive spaces outside of string literals and indentation.
Inconsistent spacing between SQL keywords and identifiers reduces readability and can indicate careless formatting. This rule enforces single-space separation while preserving intentional spacing in string literals and line indentation.
Rule ID: L010 Severity: Info Auto-fix: Supported
Example violations:
SELECT * FROM users <- Multiple spaces between keywords (violation) WHERE status = 'active'
Fixed output:
SELECT * FROM users <- Single spaces WHERE status = 'active'
The rule preserves:
- Leading indentation (not considered redundant)
- Spaces inside string literals ('multiple spaces')
- Tabs (not replaced, only consecutive spaces are affected)
func NewRedundantWhitespaceRule ¶
func NewRedundantWhitespaceRule() *RedundantWhitespaceRule
NewRedundantWhitespaceRule creates a new L010 rule instance.
The rule detects sequences of 2 or more consecutive spaces outside of string literals and indentation, supporting automatic fixing by reducing them to single spaces.
Returns a configured RedundantWhitespaceRule ready for use with the linter.
func (*RedundantWhitespaceRule) Check ¶
Check performs the redundant whitespace check on SQL content.
Extracts non-string portions of each line and searches for sequences of 2+ spaces using regex pattern matching. Leading whitespace (indentation) is skipped. For each match, a violation is reported.
Returns a slice of violations (one per redundant whitespace sequence) and nil error.
func (*RedundantWhitespaceRule) Fix ¶
func (r *RedundantWhitespaceRule) Fix(content string, violations []linter.Violation) (string, error)
Fix removes redundant whitespace from SQL content.
Processes content line by line, reducing multiple consecutive spaces to single spaces while preserving leading indentation and spaces inside string literals.
Returns the fixed content with redundant whitespace removed, and nil error.
type TrailingWhitespaceRule ¶
TrailingWhitespaceRule (L001) detects and removes unnecessary trailing whitespace at the end of lines.
This rule identifies spaces and tabs at line endings that serve no purpose and can cause issues with version control diffs and some text editors. Trailing whitespace is commonly introduced by text editors, copy-paste operations, or inconsistent formatting practices.
Rule ID: L001 Severity: Warning Auto-fix: Supported
Example violations:
SELECT * FROM users <- Trailing spaces WHERE active = true <- Trailing tab
Fixed output:
SELECT * FROM users WHERE active = true
The rule preserves newline characters but removes all trailing spaces and tabs.
func NewTrailingWhitespaceRule ¶
func NewTrailingWhitespaceRule() *TrailingWhitespaceRule
NewTrailingWhitespaceRule creates a new L001 rule instance.
The rule detects trailing spaces and tabs on any line and supports automatic fixing by stripping all trailing whitespace.
Returns a configured TrailingWhitespaceRule ready for use with the linter.
func (*TrailingWhitespaceRule) Check ¶
Check performs the trailing whitespace check on SQL content.
Scans each line for spaces or tabs at the end (excluding newline characters). For each line with trailing whitespace, a violation is reported at the position where the trailing whitespace begins.
Empty lines are skipped as they cannot have meaningful trailing whitespace.
Returns a slice of violations (one per line with trailing whitespace) and nil error.
func (*TrailingWhitespaceRule) Fix ¶
Fix removes trailing whitespace from all lines in the SQL content.
Processes the content line by line, trimming spaces and tabs from the right side of each line. Newlines are preserved. The violations parameter is ignored since the fix is applied uniformly to all lines.
This operation is safe to apply automatically and doesn't change SQL semantics.
Returns the fixed content with all trailing whitespace removed, and nil error.