Class: SasLinter::Rules::TabExpansion
- Inherits:
-
SasLinter::Rule
- Object
- SasLinter::Rule
- SasLinter::Rules::TabExpansion
- Defined in:
- lib/sas_linter/rules/tab_expansion.rb
Overview
Flag literal TAB (\t) characters in source. SAS authoring
conventions strongly prefer spaces — tabs render at different
widths in different editors and break the column alignment
SAS sources often rely on for readability.
When autofix is true, each tab is replaced with the number
of spaces needed to reach the next column-aligned tab stop
(i.e., the standard expand(1) semantics with the configured
width). A tab in column N expands to width - (N % width)
spaces, so leading whitespace, mid-line alignment, and pre-
token padding all stay column-aligned post-fix.
Recognized config options:
width: integer (default 8)
autofix: true | false (default false)
Constant Summary collapse
- DEFAULT_WIDTH =
8
Instance Attribute Summary collapse
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Class Method Summary collapse
Instance Method Summary collapse
-
#autofix(source) ⇒ Object
Replace every tab with
width - (col % width)spaces, wherecolis the post-expansion column of the tab. -
#check(_tokens, path:, all_tokens: nil, source: nil) ⇒ Object
rubocop:disable Lint/UnusedMethodArgument.
-
#initialize(width: DEFAULT_WIDTH, autofix: false) ⇒ TabExpansion
constructor
A new instance of TabExpansion.
Methods inherited from SasLinter::Rule
all, #autofix?, description, fetch, inherited, register, registry, rule_id, severity
Constructor Details
#initialize(width: DEFAULT_WIDTH, autofix: false) ⇒ TabExpansion
Returns a new instance of TabExpansion.
43 44 45 46 47 48 |
# File 'lib/sas_linter/rules/tab_expansion.rb', line 43 def initialize(width: DEFAULT_WIDTH, autofix: false) super(autofix: autofix) raise ArgumentError, "width must be positive (got #{width})" if width.to_i < 1 @width = Integer(width) end |
Instance Attribute Details
#width ⇒ Object (readonly)
Returns the value of attribute width.
41 42 43 |
# File 'lib/sas_linter/rules/tab_expansion.rb', line 41 def width @width end |
Class Method Details
.from_config(opts = {}) ⇒ Object
33 34 35 36 37 38 39 |
# File 'lib/sas_linter/rules/tab_expansion.rb', line 33 def self.from_config(opts = {}) opts = opts.transform_keys(&:to_s) new( width: Integer(opts.fetch("width", DEFAULT_WIDTH)), autofix: opts["autofix"] ? true : false ) end |
.supports_autofix? ⇒ Boolean
29 30 31 |
# File 'lib/sas_linter/rules/tab_expansion.rb', line 29 def self.supports_autofix? true end |
Instance Method Details
#autofix(source) ⇒ Object
Replace every tab with width - (col % width) spaces, where
col is the post-expansion column of the tab. Re-counts per
line so the line terminator resets the column.
75 76 77 |
# File 'lib/sas_linter/rules/tab_expansion.rb', line 75 def autofix(source) source.each_line.map { |line| (line) }.join end |
#check(_tokens, path:, all_tokens: nil, source: nil) ⇒ Object
rubocop:disable Lint/UnusedMethodArgument
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/sas_linter/rules/tab_expansion.rb', line 50 def check(_tokens, path:, all_tokens: nil, source: nil) # rubocop:disable Lint/UnusedMethodArgument return [] unless source findings = [] source.each_line.with_index do |line, idx| chomped = line.sub(/\r?\n\z/, "") next unless chomped.include?("\t") chomped.each_char.with_index do |ch, col| next unless ch == "\t" findings << finding( line: idx + 1, column: col + 1, message: "tab character#{autofix? ? " (expanded to #{@width}-space tab stop)" : ''}", path: path ) end end findings end |