-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Hello! I would like to add a linter to detect instance variables in Slim templates. Replacing them with local variables is often encouraged in Rails partial templates, but here I expect using the `include` configuration option to define the targeted files so this linter can be used together with not only partial templates but any glob pattern you like. The linter itself uses the work done on the Rubocop linter - namely the Ruby code extractor. This linter parses the extracted ruby code and searches for instance variables in there. It also uses the extracted code source map to report proper line numbers. ![image](https://github.com/sds/slim-lint/assets/462701/6deb617c-5847-4087-8b96-7f3879e6958f) This closes #155. Thanks!
- Loading branch information
Showing
5 changed files
with
139 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ Gemfile.lock | |
/coverage | ||
/pkg | ||
.ruby-version | ||
/.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# frozen_string_literal: true | ||
|
||
module SlimLint | ||
# Searches for instance variables in partial or other templates. | ||
class Linter::InstanceVariables < Linter | ||
include LinterRegistry | ||
|
||
on_start do |_sexp| | ||
processed_sexp = SlimLint::RubyExtractEngine.new.call(document.source) | ||
|
||
extractor = SlimLint::RubyExtractor.new | ||
extracted_source = extractor.extract(processed_sexp) | ||
next if extracted_source.source.empty? | ||
|
||
parsed_ruby = parse_ruby(extracted_source.source) | ||
next unless parsed_ruby | ||
|
||
report_instance_variables(parsed_ruby, extracted_source.source_map) | ||
end | ||
|
||
private | ||
|
||
def report_instance_variables(parsed_ruby, source_map) | ||
parsed_ruby.each_node do |node| | ||
next unless node.ivar_type? | ||
|
||
dummy_node = Struct.new(:line) | ||
report_lint(dummy_node.new(source_map[node.loc.line]), | ||
'Avoid instance variables in the configured ' \ | ||
"view templates (found `#{node.source}`)") | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'spec_helper' | ||
|
||
describe SlimLint::Linter::InstanceVariables do | ||
include_context 'linter' | ||
|
||
context 'with no instance variables' do | ||
let(:slim) { <<-SLIM } | ||
h1 Hello world! | ||
SLIM | ||
|
||
it { should_not report_lint } | ||
end | ||
|
||
context 'with instance variables in static contexts only' do | ||
let(:slim) { <<-SLIM } | ||
- if "@harmless_variable" | ||
= "@another_harmless_variable" | ||
p @and_another | ||
' \#{"@and_another"} | ||
SLIM | ||
|
||
it { should_not report_lint } | ||
end | ||
|
||
context 'with instance variables in control code' do | ||
let(:slim) { <<-SLIM } | ||
- if @world | ||
' hello world | ||
- call(arg: @hello) | ||
SLIM | ||
|
||
it { should report_lint line: 1 } | ||
it { should report_lint line: 3 } | ||
end | ||
|
||
context 'with instance variables in output code' do | ||
let(:slim) { <<-SLIM } | ||
p | ||
' hello | ||
= @world | ||
== call(arg: @hello) | ||
span = @some_variable | ||
SLIM | ||
|
||
it { should report_lint line: 3 } | ||
it { should report_lint line: 4 } | ||
it { should report_lint line: 5 } | ||
end | ||
|
||
context 'with instance variables in interpolated code' do | ||
let(:slim) { <<-SLIM } | ||
' \#{@hello} | ||
SLIM | ||
|
||
it { should report_lint line: 1 } | ||
end | ||
end |