From 93dd7d446fbd2eeda8a3a3a260b296fb3b349724 Mon Sep 17 00:00:00 2001 From: Vitalii Elenhaupt Date: Tue, 31 Oct 2017 20:29:30 +0200 Subject: [PATCH] AST parsing closes #2 --- spec/ameba/rules/line_length_spec.cr | 6 ++--- spec/ameba/rules/trailing_blank_lines_spec.cr | 10 ++++---- spec/ameba/rules/trailing_whitespace_spec.cr | 6 ++--- spec/ameba/source_spec.cr | 23 ++++++++++++------- src/ameba.cr | 2 +- src/ameba/rules/trailing_blank_lines.cr | 2 +- src/ameba/source.cr | 18 ++++++++------- 7 files changed, 38 insertions(+), 29 deletions(-) diff --git a/spec/ameba/rules/line_length_spec.cr b/spec/ameba/rules/line_length_spec.cr index f6189c90..0ae1972b 100644 --- a/spec/ameba/rules/line_length_spec.cr +++ b/spec/ameba/rules/line_length_spec.cr @@ -6,17 +6,17 @@ module Ameba::Rules describe LineLength do it "passes if all lines are shorter than 80 symbols" do - source = Source.new "", "short line" + source = Source.new "short line" subject.catch(source).valid?.should be_true end it "fails if there is at least one line longer than 79 symbols" do - source = Source.new "", long_line + source = Source.new long_line subject.catch(source).valid?.should be_false end it "reports rule, pos and message" do - source = Source.new "", long_line + source = Source.new long_line subject.catch(source).valid?.should be_false error = source.errors.first diff --git a/spec/ameba/rules/trailing_blank_lines_spec.cr b/spec/ameba/rules/trailing_blank_lines_spec.cr index 7fc34061..1c7e5572 100644 --- a/spec/ameba/rules/trailing_blank_lines_spec.cr +++ b/spec/ameba/rules/trailing_blank_lines_spec.cr @@ -5,27 +5,27 @@ module Ameba::Rules describe TrailingBlankLines do it "passes if there is no blank lines at the end" do - source = Source.new "", "no-blankline" + source = Source.new "no-blankline" subject.catch(source).valid?.should be_true end it "fails if there is a blank line at the end of a source" do - source = Source.new "", "a = 1\n \n " + source = Source.new "a = 1\n \n " subject.catch(source).valid?.should be_false end it "passes if source is empty" do - source = Source.new "", "" + source = Source.new "" subject.catch(source).valid?.should be_true end it "passes if last line is not blank" do - source = Source.new "", "\n\n\n puts 22" + source = Source.new "\n\n\n puts 22" subject.catch(source).valid?.should be_true end it "reports rule, pos and message" do - source = Source.new "", "a = 1\n\n " + source = Source.new "a = 1\n\n " subject.catch(source) error = source.errors.first diff --git a/spec/ameba/rules/trailing_whitespace_spec.cr b/spec/ameba/rules/trailing_whitespace_spec.cr index 6c799563..c88d0868 100644 --- a/spec/ameba/rules/trailing_whitespace_spec.cr +++ b/spec/ameba/rules/trailing_whitespace_spec.cr @@ -5,17 +5,17 @@ module Ameba::Rules describe TrailingWhitespace do it "passes if all lines do not have trailing whitespace" do - source = Source.new "", "no-whispace" + source = Source.new "no-whispace" subject.catch(source).valid?.should be_true end it "fails if there is a line with trailing whitespace" do - source = Source.new "", "whitespace at the end " + source = Source.new "whitespace at the end " subject.catch(source).valid?.should be_false end it "reports rule, pos and message" do - source = Source.new "", "a = 1\n b = 2 " + source = Source.new "a = 1\n b = 2 " subject.catch(source).valid?.should be_false error = source.errors.first diff --git a/spec/ameba/source_spec.cr b/spec/ameba/source_spec.cr index b6b3c394..1a726068 100644 --- a/spec/ameba/source_spec.cr +++ b/spec/ameba/source_spec.cr @@ -3,20 +3,17 @@ require "../spec_helper" module Ameba describe Source do describe ".new" do - it "allows to create a source by file path" do - Source.new(__FILE__).path.should eq __FILE__ - end - it "allows to create a source by content and path" do - s = Source.new(__FILE__, "content") - s.path.should eq __FILE__ - s.lines.should eq %w(content) + s = Source.new("content", "path") + s.path.should eq "path" + s.content.should eq "content" + s.lines.should eq ["content"] end end describe "#error" do it "adds and error" do - s = Source.new(__FILE__) + s = Source.new "" s.error(DummyRule.new, 23, "Error!") s.errors.size.should eq 1 s.errors.first.rule.should_not be_nil @@ -24,5 +21,15 @@ module Ameba s.errors.first.message.should eq "Error!" end end + + describe "#ast" do + it "returns ast nodes" do + s = Source.new %( + class A; end + class B; end + ) + s.ast.to_s.should eq "class A\nend\nclass B\nend\n" + end + end end end diff --git a/src/ameba.cr b/src/ameba.cr index c2de892d..3afe3ce2 100644 --- a/src/ameba.cr +++ b/src/ameba.cr @@ -13,7 +13,7 @@ module Ameba end def run(files, formatter : Formatter) - sources = files.map { |path| Source.new(path) } + sources = files.map { |path| Source.new(File.read path) } reporter = Reporter.new formatter reporter.start sources diff --git a/src/ameba/rules/trailing_blank_lines.cr b/src/ameba/rules/trailing_blank_lines.cr index 24e8034d..26892e27 100644 --- a/src/ameba/rules/trailing_blank_lines.cr +++ b/src/ameba/rules/trailing_blank_lines.cr @@ -1,7 +1,7 @@ # A rule that disallows trailing blank lines at the end of the source file. Ameba.rule TrailingBlankLines do |source| - if source.lines.size > 1 && source.lines[-2, 2].join.strip == "" + if source.lines.size > 1 && source.lines[-2, 2].join.strip.empty? source.error self, source.lines.size, "Blank lines detected at the end of the file" end diff --git a/src/ameba/source.cr b/src/ameba/source.cr index 92ed616f..3401b9cb 100644 --- a/src/ameba/source.cr +++ b/src/ameba/source.cr @@ -1,8 +1,9 @@ +require "compiler/crystal/syntax/*" + module Ameba # An entity that represents a Crystal source file. # Has path, lines of code and errors reported by rules. class Source - # Represents an error caught by Ameba. # # Each error has the rule that created this error, @@ -14,14 +15,11 @@ module Ameba getter lines : Array(String) getter errors = [] of Error - getter path : String + getter path : String? + getter content : String - def initialize(@path : String) - @lines = File.read_lines(@path) - end - - def initialize(@path : String, content : String) - @lines = content.split("\n") + def initialize(@content : String, @path = nil) + @lines = @content.split("\n") end def error(rule : Rule, line_number : Int32, message : String) @@ -31,5 +29,9 @@ module Ameba def valid? errors.empty? end + + def ast + Crystal::Parser.new(@content).tap { |p| p.filename = @path }.parse + end end end