AST parsing

closes #2
This commit is contained in:
Vitalii Elenhaupt 2017-10-31 20:29:30 +02:00
parent b8eeac469a
commit 93dd7d446f
No known key found for this signature in database
GPG key ID: 7558EF3A4056C706
7 changed files with 38 additions and 29 deletions

View file

@ -6,17 +6,17 @@ module Ameba::Rules
describe LineLength do describe LineLength do
it "passes if all lines are shorter than 80 symbols" 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 subject.catch(source).valid?.should be_true
end end
it "fails if there is at least one line longer than 79 symbols" do 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 subject.catch(source).valid?.should be_false
end end
it "reports rule, pos and message" do it "reports rule, pos and message" do
source = Source.new "", long_line source = Source.new long_line
subject.catch(source).valid?.should be_false subject.catch(source).valid?.should be_false
error = source.errors.first error = source.errors.first

View file

@ -5,27 +5,27 @@ module Ameba::Rules
describe TrailingBlankLines do describe TrailingBlankLines do
it "passes if there is no blank lines at the end" 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 subject.catch(source).valid?.should be_true
end end
it "fails if there is a blank line at the end of a source" do 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 subject.catch(source).valid?.should be_false
end end
it "passes if source is empty" do it "passes if source is empty" do
source = Source.new "", "" source = Source.new ""
subject.catch(source).valid?.should be_true subject.catch(source).valid?.should be_true
end end
it "passes if last line is not blank" do 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 subject.catch(source).valid?.should be_true
end end
it "reports rule, pos and message" do it "reports rule, pos and message" do
source = Source.new "", "a = 1\n\n " source = Source.new "a = 1\n\n "
subject.catch(source) subject.catch(source)
error = source.errors.first error = source.errors.first

View file

@ -5,17 +5,17 @@ module Ameba::Rules
describe TrailingWhitespace do describe TrailingWhitespace do
it "passes if all lines do not have trailing whitespace" 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 subject.catch(source).valid?.should be_true
end end
it "fails if there is a line with trailing whitespace" do 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 subject.catch(source).valid?.should be_false
end end
it "reports rule, pos and message" do 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 subject.catch(source).valid?.should be_false
error = source.errors.first error = source.errors.first

View file

@ -3,20 +3,17 @@ require "../spec_helper"
module Ameba module Ameba
describe Source do describe Source do
describe ".new" 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 it "allows to create a source by content and path" do
s = Source.new(__FILE__, "content") s = Source.new("content", "path")
s.path.should eq __FILE__ s.path.should eq "path"
s.lines.should eq %w(content) s.content.should eq "content"
s.lines.should eq ["content"]
end end
end end
describe "#error" do describe "#error" do
it "adds and error" do it "adds and error" do
s = Source.new(__FILE__) s = Source.new ""
s.error(DummyRule.new, 23, "Error!") s.error(DummyRule.new, 23, "Error!")
s.errors.size.should eq 1 s.errors.size.should eq 1
s.errors.first.rule.should_not be_nil s.errors.first.rule.should_not be_nil
@ -24,5 +21,15 @@ module Ameba
s.errors.first.message.should eq "Error!" s.errors.first.message.should eq "Error!"
end end
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
end end

View file

@ -13,7 +13,7 @@ module Ameba
end end
def run(files, formatter : Formatter) 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 = Reporter.new formatter
reporter.start sources reporter.start sources

View file

@ -1,7 +1,7 @@
# A rule that disallows trailing blank lines at the end of the source file. # A rule that disallows trailing blank lines at the end of the source file.
Ameba.rule TrailingBlankLines do |source| 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, source.error self, source.lines.size,
"Blank lines detected at the end of the file" "Blank lines detected at the end of the file"
end end

View file

@ -1,8 +1,9 @@
require "compiler/crystal/syntax/*"
module Ameba module Ameba
# An entity that represents a Crystal source file. # An entity that represents a Crystal source file.
# Has path, lines of code and errors reported by rules. # Has path, lines of code and errors reported by rules.
class Source class Source
# Represents an error caught by Ameba. # Represents an error caught by Ameba.
# #
# Each error has the rule that created this error, # Each error has the rule that created this error,
@ -14,14 +15,11 @@ module Ameba
getter lines : Array(String) getter lines : Array(String)
getter errors = [] of Error getter errors = [] of Error
getter path : String getter path : String?
getter content : String
def initialize(@path : String) def initialize(@content : String, @path = nil)
@lines = File.read_lines(@path) @lines = @content.split("\n")
end
def initialize(@path : String, content : String)
@lines = content.split("\n")
end end
def error(rule : Rule, line_number : Int32, message : String) def error(rule : Rule, line_number : Int32, message : String)
@ -31,5 +29,9 @@ module Ameba
def valid? def valid?
errors.empty? errors.empty?
end end
def ast
Crystal::Parser.new(@content).tap { |p| p.filename = @path }.parse
end
end end
end end