Skip to content

Commit

Permalink
Add support for crlf and lf styles in Style/EndOfLine
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas054 authored and bbatsov committed Jan 26, 2017
1 parent 0293ef2 commit e88d5ee
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 54 deletions.
6 changes: 6 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,12 @@ Style/Encoding:
- never
AutoCorrectEncodingComment: '# encoding: utf-8'

Style/EndOfLine:
EnforcedStyle: lf
SupportedStyles:
- lf
- crlf

Style/ExtraSpacing:
# When true, allows most uses of extra spacing if the intent is to align
# things with the previous or next line, not counting empty lines or comment
Expand Down
23 changes: 20 additions & 3 deletions lib/rubocop/cop/style/end_of_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ module Cop
module Style
# This cop checks for Windows-style line endings in the source code.
class EndOfLine < Cop
MSG = 'Carriage return character detected.'.freeze
include ConfigurableEnforcedStyle

MSG_DETECTED = 'Carriage return character detected.'.freeze
MSG_MISSING = 'Carriage return character missing.'.freeze

def investigate(processed_source)
last_token = processed_source.tokens.last
Expand All @@ -14,16 +17,30 @@ def investigate(processed_source)

processed_source.raw_source.each_line.with_index do |line, index|
break if index >= last_line
next unless line =~ /\r$/
msg = offense_message(line)
next unless msg
next if unimportant_missing_cr?(index, last_line, line)

range =
source_range(processed_source.buffer, index + 1, 0, line.length)
add_offense(nil, range, MSG)
add_offense(nil, range, msg)
# Usually there will be carriage return characters on all or none
# of the lines in a file, so we report only one offense.
break
end
end

# If there is no LF on the last line, we don't care if there's no CR.
def unimportant_missing_cr?(index, last_line, line)
style == :crlf && index == last_line - 1 && line !~ /\n$/
end

def offense_message(line)
case style
when :lf then MSG_DETECTED if line =~ /\r$/
else MSG_MISSING if line !~ /\r$/
end
end
end
end
end
Expand Down
176 changes: 125 additions & 51 deletions spec/rubocop/cop/style/end_of_line_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,78 +3,152 @@

require 'spec_helper'

describe RuboCop::Cop::Style::EndOfLine do
subject(:cop) { described_class.new }
describe RuboCop::Cop::Style::EndOfLine, :config do
subject(:cop) { described_class.new(config) }

it 'accepts an empty file' do
inspect_source_file(cop, '')
expect(cop.offenses).to be_empty
shared_examples 'all configurations' do
it 'accepts an empty file' do
inspect_source_file(cop, '')
expect(cop.offenses).to be_empty
end
end

it 'registers an offense for CR+LF' do
inspect_source_file(cop, ['x=0', '', "y=1\r"])
expect(cop.messages).to eq(['Carriage return character detected.'])
shared_examples 'iso-8859-15' do |eol|
it 'can inspect non-UTF-8 encoded source with proper encoding comment' do
inspect_source_file(cop, ["# coding: ISO-8859-15#{eol}",
"# Euro symbol: \xa4#{eol}"])
expect(cop.offenses.size).to eq(1)
end
end

it 'highlights the whole offending line' do
inspect_source_file(cop, ['x=0', '', "y=1\r"])
expect(cop.highlights).to eq(["y=1\r"])
end
context 'when EnforcedStyle is crlf' do
let(:cop_config) { { 'EnforcedStyle' => 'crlf' } }
let(:messages) { ['Carriage return character missing.'] }
include_examples 'all configurations'

it 'registers an offense for CR at end of file' do
inspect_source_file(cop, "x=0\r")
expect(cop.messages).to eq(['Carriage return character detected.'])
end
it 'registers an offense for CR+LF' do
inspect_source_file(cop, ['x=0', '', "y=1\r"])
expect(cop.messages).to eq(messages)
expect(cop.offenses.map(&:line)).to eq([1])
end

it 'does not register offenses after __END__' do
inspect_source(cop, ['x=0',
'__END__',
"x=0\r"])
expect(cop.offenses).to be_empty
end
it 'highlights the whole offending line' do
inspect_source_file(cop, ['x=0', '', "y=1\r"])
expect(cop.highlights).to eq(["x=0\n"])
end

shared_examples 'iso-8859-15' do
it 'can inspect non-UTF-8 encoded source with proper encoding comment' do
inspect_source_file(cop, ['# coding: ISO-8859-15\r',
"# Euro symbol: \xa4\r"])
expect(cop.offenses.size).to eq(1)
it 'does not register offense for no CR at end of file' do
inspect_source_file(cop, 'x=0')
expect(cop.offenses).to be_empty
end
end

context 'when there are many lines ending with CR+LF' do
it 'registers only one offense' do
inspect_source_file(cop, ['x=0', '', 'y=1'].join("\r\n"))
expect(cop.messages.size).to eq(1)
it 'does not register offenses after __END__' do
inspect_source(cop, ["x=0\r",
'__END__',
'x=0'])
expect(cop.offenses).to be_empty
end

include_examples 'iso-8859-15'
end
context 'and there are many lines ending with LF' do
it 'registers only one offense' do
inspect_source_file(cop, ['x=0', '', 'y=1'].join("\n"))
expect(cop.messages.size).to eq(1)
end

context 'when the default external encoding is US_ASCII' do
around do |example|
orig_encoding = Encoding.default_external
Encoding.default_external = Encoding::US_ASCII
example.run
Encoding.default_external = orig_encoding
include_examples 'iso-8859-15', ''
end

it 'does not crash on UTF-8 encoded non-ascii characters' do
inspect_source_file(cop,
['# encoding: UTF-8',
'class Epd::ReportsController < EpdAreaController',
" 'terecht bij uw ROM-coördinator.'",
'end'].join("\n"))
expect(cop.offenses).to be_empty
context 'and the default external encoding is US_ASCII' do
around do |example|
orig_encoding = Encoding.default_external
Encoding.default_external = Encoding::US_ASCII
example.run
Encoding.default_external = orig_encoding
end

it 'does not crash on UTF-8 encoded non-ascii characters' do
source = ['# encoding: UTF-8',
'class Epd::ReportsController < EpdAreaController',
" 'terecht bij uw ROM-coördinator.'",
'end'].join("\r\n")
inspect_source_file(cop, source)
expect(cop.offenses).to be_empty
end

include_examples 'iso-8859-15', ''
end

include_examples 'iso-8859-15'
context 'and source is a string' do
it 'registers an offense' do
inspect_source(cop, "x=0\ny=1")

expect(cop.messages).to eq(['Carriage return character missing.'])
end
end
end

context 'when source is a string' do
it 'registers an offense' do
inspect_source(cop, "x=0\r")
context 'when EnforcedStyle is lf' do
let(:cop_config) { { 'EnforcedStyle' => 'lf' } }
include_examples 'all configurations'

it 'registers an offense for CR+LF' do
inspect_source_file(cop, ['x=0', '', "y=1\r"])
expect(cop.messages).to eq(['Carriage return character detected.'])
expect(cop.offenses.map(&:line)).to eq([3])
end

it 'highlights the whole offending line' do
inspect_source_file(cop, ['x=0', '', "y=1\r"])
expect(cop.highlights).to eq(["y=1\r"])
end

it 'registers an offense for CR at end of file' do
inspect_source_file(cop, "x=0\r")
expect(cop.messages).to eq(['Carriage return character detected.'])
end

it 'does not register offenses after __END__' do
inspect_source(cop, ['x=0',
'__END__',
"x=0\r"])
expect(cop.offenses).to be_empty
end

context 'and there are many lines ending with CR+LF' do
it 'registers only one offense' do
inspect_source_file(cop, ['x=0', '', 'y=1'].join("\r\n"))
expect(cop.messages.size).to eq(1)
end

include_examples 'iso-8859-15', "\r"
end

context 'and the default external encoding is US_ASCII' do
around do |example|
orig_encoding = Encoding.default_external
Encoding.default_external = Encoding::US_ASCII
example.run
Encoding.default_external = orig_encoding
end

it 'does not crash on UTF-8 encoded non-ascii characters' do
source = ['# encoding: UTF-8',
'class Epd::ReportsController < EpdAreaController',
" 'terecht bij uw ROM-coördinator.'",
'end'].join("\n")
inspect_source_file(cop, source)
expect(cop.offenses).to be_empty
end

include_examples 'iso-8859-15', "\r"
end

context 'and source is a string' do
it 'registers an offense' do
inspect_source(cop, "x=0\r")

expect(cop.messages).to eq(['Carriage return character detected.'])
end
end
end
end

0 comments on commit e88d5ee

Please sign in to comment.