mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	
						commit
						42235c02be
					
				
					 18 changed files with 267 additions and 18 deletions
				
			
		| 
						 | 
					@ -114,6 +114,29 @@ module Ameba::Cli
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      context "--fail-level" do
 | 
				
			||||||
 | 
					        it "configures fail level Refactoring" do
 | 
				
			||||||
 | 
					          c = Cli.parse_args %w(--fail-level refactoring)
 | 
				
			||||||
 | 
					          c.fail_level.should eq Severity::Refactoring
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it "configures fail level Warning" do
 | 
				
			||||||
 | 
					          c = Cli.parse_args %w(--fail-level Warning)
 | 
				
			||||||
 | 
					          c.fail_level.should eq Severity::Warning
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it "configures fail level Error" do
 | 
				
			||||||
 | 
					          c = Cli.parse_args %w(--fail-level error)
 | 
				
			||||||
 | 
					          c.fail_level.should eq Severity::Error
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it "raises if fail level is incorrect" do
 | 
				
			||||||
 | 
					          expect_raises(Exception, "Incorrect severity name JohnDoe") do
 | 
				
			||||||
 | 
					            Cli.parse_args %w(--fail-level JohnDoe)
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      it "accepts unknown args as globs" do
 | 
					      it "accepts unknown args as globs" do
 | 
				
			||||||
        c = Cli.parse_args %w(source1.cr source2.cr)
 | 
					        c = Cli.parse_args %w(source1.cr source2.cr)
 | 
				
			||||||
        c.globs.should eq %w(source1.cr source2.cr)
 | 
					        c.globs.should eq %w(source1.cr source2.cr)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,19 @@ module Ameba::Formatter
 | 
				
			||||||
          log.should contain "      \e[33m^\e[0m"
 | 
					          log.should contain "      \e[33m^\e[0m"
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        it "writes severity" do
 | 
				
			||||||
 | 
					          output.clear
 | 
				
			||||||
 | 
					          s = Source.new(%(
 | 
				
			||||||
 | 
					            a = 22
 | 
				
			||||||
 | 
					            puts a
 | 
				
			||||||
 | 
					          )).tap do |source|
 | 
				
			||||||
 | 
					            source.add_issue(DummyRule.new, {1, 5}, "DummyRuleError")
 | 
				
			||||||
 | 
					          end
 | 
				
			||||||
 | 
					          subject.finished [s]
 | 
				
			||||||
 | 
					          log = output.to_s
 | 
				
			||||||
 | 
					          log.should contain "[R]"
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        it "doesn't write affected code if it is disabled" do
 | 
					        it "doesn't write affected code if it is disabled" do
 | 
				
			||||||
          output.clear
 | 
					          output.clear
 | 
				
			||||||
          s = Source.new(%(
 | 
					          s = Source.new(%(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,7 @@ module Ameba
 | 
				
			||||||
        source = Source.new "a = 42", "source.cr"
 | 
					        source = Source.new "a = 42", "source.cr"
 | 
				
			||||||
        output = explanation(source)
 | 
					        output = explanation(source)
 | 
				
			||||||
        output.should contain "RULE INFO"
 | 
					        output.should contain "RULE INFO"
 | 
				
			||||||
 | 
					        output.should contain "Refactoring"
 | 
				
			||||||
        output.should contain "Ameba/ErrorRule"
 | 
					        output.should contain "Ameba/ErrorRule"
 | 
				
			||||||
        output.should contain "Always adds an error at 1:1"
 | 
					        output.should contain "Always adds an error at 1:1"
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ module Ameba::Formatter
 | 
				
			||||||
        subject = flycheck
 | 
					        subject = flycheck
 | 
				
			||||||
        subject.source_finished s
 | 
					        subject.source_finished s
 | 
				
			||||||
        subject.output.to_s.should eq(
 | 
					        subject.output.to_s.should eq(
 | 
				
			||||||
          "source.cr:1:2: E: [#{DummyRule.rule_name}] message\n"
 | 
					          "source.cr:1:2: R: [#{DummyRule.rule_name}] message\n"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ module Ameba::Formatter
 | 
				
			||||||
        subject = flycheck
 | 
					        subject = flycheck
 | 
				
			||||||
        subject.source_finished s
 | 
					        subject.source_finished s
 | 
				
			||||||
        subject.output.to_s.should eq(
 | 
					        subject.output.to_s.should eq(
 | 
				
			||||||
          "source.cr:1:2: E: [#{DummyRule.rule_name}] multi line\n"
 | 
					          "source.cr:1:2: R: [#{DummyRule.rule_name}] multi line\n"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,14 @@ module Ameba
 | 
				
			||||||
        result["sources"][0]["issues"][0]["rule_name"].should eq DummyRule.rule_name
 | 
					        result["sources"][0]["issues"][0]["rule_name"].should eq DummyRule.rule_name
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "shows severity" do
 | 
				
			||||||
 | 
					        s = Source.new ""
 | 
				
			||||||
 | 
					        s.add_issue DummyRule.new, {1, 2}, "message"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = get_result [s]
 | 
				
			||||||
 | 
					        result["sources"][0]["issues"][0]["severity"].should eq "Refactoring"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      it "shows a message" do
 | 
					      it "shows a message" do
 | 
				
			||||||
        s = Source.new ""
 | 
					        s = Source.new ""
 | 
				
			||||||
        s.add_issue DummyRule.new, {1, 2}, "message"
 | 
					        s.add_issue DummyRule.new, {1, 2}, "message"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,10 @@ module Ameba
 | 
				
			||||||
        create_todo.should contain "DummyRule"
 | 
					        create_todo.should contain "DummyRule"
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "creates a todo with severity" do
 | 
				
			||||||
 | 
					        create_todo.should contain "Refactoring"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      it "creates a todo with problems count" do
 | 
					      it "creates a todo with problems count" do
 | 
				
			||||||
        create_todo.should contain "Problems found: 1"
 | 
					        create_todo.should contain "Problems found: 1"
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,5 +33,9 @@ module Ameba::Rule::Lint
 | 
				
			||||||
      issue.location.to_s.should eq "source.cr:1:11"
 | 
					      issue.location.to_s.should eq "source.cr:1:11"
 | 
				
			||||||
      issue.message.should eq "unexpected token: end (expected ';' or newline)"
 | 
					      issue.message.should eq "unexpected token: end (expected ';' or newline)"
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it "has highest severity" do
 | 
				
			||||||
 | 
					      subject.severity.should eq Severity::Error
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ module Ameba
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe Runner do
 | 
					  describe Runner do
 | 
				
			||||||
    formatter = DummyFormatter.new
 | 
					    formatter = DummyFormatter.new
 | 
				
			||||||
 | 
					    default_severity = Severity::Refactoring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    describe "#run" do
 | 
					    describe "#run" do
 | 
				
			||||||
      it "returns self" do
 | 
					      it "returns self" do
 | 
				
			||||||
| 
						 | 
					@ -49,7 +50,7 @@ module Ameba
 | 
				
			||||||
          rules << rule
 | 
					          rules << rule
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Runner.new(all_rules, [source], formatter).run.success?.should be_true
 | 
					        Runner.new(all_rules, [source], formatter, default_severity).run.success?.should be_true
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      context "invalid syntax" do
 | 
					      context "invalid syntax" do
 | 
				
			||||||
| 
						 | 
					@ -57,7 +58,7 @@ module Ameba
 | 
				
			||||||
          rules = [Rule::Lint::Syntax.new] of Rule::Base
 | 
					          rules = [Rule::Lint::Syntax.new] of Rule::Base
 | 
				
			||||||
          source = Source.new "def bad_syntax"
 | 
					          source = Source.new "def bad_syntax"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          Runner.new(rules, [source], formatter).run
 | 
					          Runner.new(rules, [source], formatter, default_severity).run
 | 
				
			||||||
          source.should_not be_valid
 | 
					          source.should_not be_valid
 | 
				
			||||||
          source.issues.first.rule.name.should eq Rule::Lint::Syntax.rule_name
 | 
					          source.issues.first.rule.name.should eq Rule::Lint::Syntax.rule_name
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,7 @@ module Ameba
 | 
				
			||||||
              when my_bad_syntax
 | 
					              when my_bad_syntax
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          Runner.new(rules, [source], formatter).run
 | 
					          Runner.new(rules, [source], formatter, default_severity).run
 | 
				
			||||||
          source.should_not be_valid
 | 
					          source.should_not be_valid
 | 
				
			||||||
          source.issues.size.should eq 1
 | 
					          source.issues.size.should eq 1
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
| 
						 | 
					@ -83,7 +84,7 @@ module Ameba
 | 
				
			||||||
            a = 1 # ameba:disable LineLength
 | 
					            a = 1 # ameba:disable LineLength
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          Runner.new(rules, [source], formatter).run
 | 
					          Runner.new(rules, [source], formatter, default_severity).run
 | 
				
			||||||
          source.should_not be_valid
 | 
					          source.should_not be_valid
 | 
				
			||||||
          source.issues.first.rule.name.should eq Rule::Lint::UnneededDisableDirective.rule_name
 | 
					          source.issues.first.rule.name.should eq Rule::Lint::UnneededDisableDirective.rule_name
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
| 
						 | 
					@ -107,7 +108,7 @@ module Ameba
 | 
				
			||||||
            a = 1
 | 
					            a = 1
 | 
				
			||||||
          ), "source.cr"
 | 
					          ), "source.cr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        runner = Runner.new(rules, [source], formatter).run
 | 
					        runner = Runner.new(rules, [source], formatter, default_severity).run
 | 
				
			||||||
        runner.explain({file: "source.cr", line: 1, column: 1}, io)
 | 
					        runner.explain({file: "source.cr", line: 1, column: 1}, io)
 | 
				
			||||||
        io.to_s.should_not be_empty
 | 
					        io.to_s.should_not be_empty
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					@ -119,7 +120,7 @@ module Ameba
 | 
				
			||||||
            a = 1
 | 
					            a = 1
 | 
				
			||||||
          ), "source.cr"
 | 
					          ), "source.cr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        runner = Runner.new(rules, [source], formatter).run
 | 
					        runner = Runner.new(rules, [source], formatter, default_severity).run
 | 
				
			||||||
        runner.explain({file: "source.cr", line: 1, column: 2}, io)
 | 
					        runner.explain({file: "source.cr", line: 1, column: 2}, io)
 | 
				
			||||||
        io.to_s.should be_empty
 | 
					        io.to_s.should be_empty
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					@ -139,7 +140,15 @@ module Ameba
 | 
				
			||||||
        s = Source.new %q(
 | 
					        s = Source.new %q(
 | 
				
			||||||
          WrongConstant = 5
 | 
					          WrongConstant = 5
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        Runner.new(rules, [s], formatter).run.success?.should be_false
 | 
					        Runner.new(rules, [s], formatter, default_severity).run.success?.should be_false
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "depends on the level of severity" do
 | 
				
			||||||
 | 
					        rules = Rule.rules.map &.new.as(Rule::Base)
 | 
				
			||||||
 | 
					        s = Source.new %q(WrongConstant = 5)
 | 
				
			||||||
 | 
					        Runner.new(rules, [s], formatter, Severity::Error).run.success?.should be_true
 | 
				
			||||||
 | 
					        Runner.new(rules, [s], formatter, Severity::Warning).run.success?.should be_true
 | 
				
			||||||
 | 
					        Runner.new(rules, [s], formatter, Severity::Refactoring).run.success?.should be_false
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										107
									
								
								spec/ameba/severity_spec.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								spec/ameba/severity_spec.cr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,107 @@
 | 
				
			||||||
 | 
					require "../spec_helper"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Ameba
 | 
				
			||||||
 | 
					  describe Severity do
 | 
				
			||||||
 | 
					    describe "#symbol" do
 | 
				
			||||||
 | 
					      it "returns the symbol for each severity in the enum" do
 | 
				
			||||||
 | 
					        Severity.values.each do |severity|
 | 
				
			||||||
 | 
					          severity.symbol.should_not be_nil
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "returns symbol for Error" do
 | 
				
			||||||
 | 
					        Severity::Error.symbol.should eq 'E'
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "returns symbol for Warning" do
 | 
				
			||||||
 | 
					        Severity::Warning.symbol.should eq 'W'
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "returns symbol for Refactoring" do
 | 
				
			||||||
 | 
					        Severity::Refactoring.symbol.should eq 'R'
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    describe ".from_name" do
 | 
				
			||||||
 | 
					      it "creates error severity by name" do
 | 
				
			||||||
 | 
					        Severity.from_name("Error").should eq Severity::Error
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "creates warning severity by name" do
 | 
				
			||||||
 | 
					        Severity.from_name("Warning").should eq Severity::Warning
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "creates refactoring severity by name" do
 | 
				
			||||||
 | 
					        Severity.from_name("Refactoring").should eq Severity::Refactoring
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "raises when name is incorrect" do
 | 
				
			||||||
 | 
					        expect_raises(Exception, "Incorrect severity name BadName. Try one of [Error, Warning, Refactoring]") do
 | 
				
			||||||
 | 
					          Severity.from_name("BadName")
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  struct SeverityConvertable
 | 
				
			||||||
 | 
					    YAML.mapping(
 | 
				
			||||||
 | 
					      severity: {type: Severity, converter: SeverityYamlConverter}
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe SeverityYamlConverter do
 | 
				
			||||||
 | 
					    describe ".from_yaml" do
 | 
				
			||||||
 | 
					      it "converts from yaml to Severity::Error" do
 | 
				
			||||||
 | 
					        yaml = {severity: "error"}.to_yaml
 | 
				
			||||||
 | 
					        converted = SeverityConvertable.from_yaml(yaml)
 | 
				
			||||||
 | 
					        converted.severity.should eq Severity::Error
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "converts from yaml to Severity::Warning" do
 | 
				
			||||||
 | 
					        yaml = {severity: "warning"}.to_yaml
 | 
				
			||||||
 | 
					        converted = SeverityConvertable.from_yaml(yaml)
 | 
				
			||||||
 | 
					        converted.severity.should eq Severity::Warning
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "converts from yaml to Severity::Refactoring" do
 | 
				
			||||||
 | 
					        yaml = {severity: "refactoring"}.to_yaml
 | 
				
			||||||
 | 
					        converted = SeverityConvertable.from_yaml(yaml)
 | 
				
			||||||
 | 
					        converted.severity.should eq Severity::Refactoring
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "raises if severity is not a scalar" do
 | 
				
			||||||
 | 
					        yaml = {severity: {refactoring: true}}.to_yaml
 | 
				
			||||||
 | 
					        expect_raises(Exception, "Severity must be a scalar") do
 | 
				
			||||||
 | 
					          SeverityConvertable.from_yaml(yaml)
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "raises if severity has a wrong type" do
 | 
				
			||||||
 | 
					        yaml = {severity: [1, 2, 3]}.to_yaml
 | 
				
			||||||
 | 
					        expect_raises(Exception, "Severity must be a scalar") do
 | 
				
			||||||
 | 
					          SeverityConvertable.from_yaml(yaml)
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    describe ".to_yaml" do
 | 
				
			||||||
 | 
					      it "converts Severity::Error to yaml" do
 | 
				
			||||||
 | 
					        yaml = {severity: "error"}.to_yaml
 | 
				
			||||||
 | 
					        converted = SeverityConvertable.from_yaml(yaml).to_yaml
 | 
				
			||||||
 | 
					        converted.should eq "---\nseverity: Error\n"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "converts Severity::Warning to yaml" do
 | 
				
			||||||
 | 
					        yaml = {severity: "warning"}.to_yaml
 | 
				
			||||||
 | 
					        converted = SeverityConvertable.from_yaml(yaml).to_yaml
 | 
				
			||||||
 | 
					        converted.should eq "---\nseverity: Warning\n"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "converts Severity::Refactoring to yaml" do
 | 
				
			||||||
 | 
					        yaml = {severity: "refactoring"}.to_yaml
 | 
				
			||||||
 | 
					        converted = SeverityConvertable.from_yaml(yaml).to_yaml
 | 
				
			||||||
 | 
					        converted.should eq "---\nseverity: Refactoring\n"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ module Ameba::Cli
 | 
				
			||||||
    opts = parse_args args
 | 
					    opts = parse_args args
 | 
				
			||||||
    config = Config.load opts.config, opts.colors?
 | 
					    config = Config.load opts.config, opts.colors?
 | 
				
			||||||
    config.globs = opts.globs
 | 
					    config.globs = opts.globs
 | 
				
			||||||
 | 
					    config.severity = opts.fail_level.not_nil! if opts.fail_level
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    configure_formatter(config, opts)
 | 
					    configure_formatter(config, opts)
 | 
				
			||||||
    configure_rules(config, opts)
 | 
					    configure_rules(config, opts)
 | 
				
			||||||
| 
						 | 
					@ -32,6 +33,7 @@ module Ameba::Cli
 | 
				
			||||||
    property only : Array(String)?
 | 
					    property only : Array(String)?
 | 
				
			||||||
    property except : Array(String)?
 | 
					    property except : Array(String)?
 | 
				
			||||||
    property location_to_explain : NamedTuple(file: String, line: Int32, column: Int32)?
 | 
					    property location_to_explain : NamedTuple(file: String, line: Int32, column: Int32)?
 | 
				
			||||||
 | 
					    property fail_level : Severity?
 | 
				
			||||||
    property? all = false
 | 
					    property? all = false
 | 
				
			||||||
    property? colors = true
 | 
					    property? colors = true
 | 
				
			||||||
    property? without_affected_code = false
 | 
					    property? without_affected_code = false
 | 
				
			||||||
| 
						 | 
					@ -82,6 +84,10 @@ module Ameba::Cli
 | 
				
			||||||
        opts.config = ""
 | 
					        opts.config = ""
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      parser.on("--fail-level SEVERITY", "Change the level of failure to exit. Defaults to Refactoring") do |level|
 | 
				
			||||||
 | 
					        opts.fail_level = Severity.from_name(level)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      parser.on("-e", "--explain PATH:line:column",
 | 
					      parser.on("-e", "--explain PATH:line:column",
 | 
				
			||||||
        "Explain an issue at a specified location") do |loc|
 | 
					        "Explain an issue at a specified location") do |loc|
 | 
				
			||||||
        configure_explain_opts(loc, opts)
 | 
					        configure_explain_opts(loc, opts)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ class Ameba::Config
 | 
				
			||||||
  setter formatter : Formatter::BaseFormatter?
 | 
					  setter formatter : Formatter::BaseFormatter?
 | 
				
			||||||
  setter globs : Array(String)?
 | 
					  setter globs : Array(String)?
 | 
				
			||||||
  getter rules : Array(Rule::Base)
 | 
					  getter rules : Array(Rule::Base)
 | 
				
			||||||
 | 
					  property severity = Severity::Refactoring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @rule_groups : Hash(String, Array(Rule::Base))
 | 
					  @rule_groups : Hash(String, Array(Rule::Base))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,6 +194,12 @@ class Ameba::Config
 | 
				
			||||||
        {% key = name.camelcase.stringify %}
 | 
					        {% key = name.camelcase.stringify %}
 | 
				
			||||||
        {% value = df[:value] %}
 | 
					        {% value = df[:value] %}
 | 
				
			||||||
        {% type = df[:type] %}
 | 
					        {% type = df[:type] %}
 | 
				
			||||||
 | 
					        {% converter = nil %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {% if key == "Severity" %}
 | 
				
			||||||
 | 
					          {% type = Severity %}
 | 
				
			||||||
 | 
					          {% converter = SeverityYamlConverter %}
 | 
				
			||||||
 | 
					        {% end %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {% if type == nil %}
 | 
					        {% if type == nil %}
 | 
				
			||||||
          {% if value.is_a? BoolLiteral %}
 | 
					          {% if value.is_a? BoolLiteral %}
 | 
				
			||||||
| 
						 | 
					@ -214,13 +221,18 @@ class Ameba::Config
 | 
				
			||||||
          {% type = Nil if type == nil %}
 | 
					          {% type = Nil if type == nil %}
 | 
				
			||||||
        {% end %}
 | 
					        {% end %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {% properties[name] = {key: key, default: value, type: type} %}
 | 
					        {% properties[name] = {key: key, default: value, type: type, converter: converter} %}
 | 
				
			||||||
      {% end %}
 | 
					      {% end %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {% if properties["enabled".id] == nil %}
 | 
					      {% if properties["enabled".id] == nil %}
 | 
				
			||||||
        {% properties["enabled".id] = {key: "Enabled", default: true, type: Bool} %}
 | 
					        {% properties["enabled".id] = {key: "Enabled", default: true, type: Bool} %}
 | 
				
			||||||
      {% end %}
 | 
					      {% end %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {% if properties["severity".id] == nil %}
 | 
				
			||||||
 | 
					        {% default = @type.name.starts_with?("Ameba::Rule::Lint") ? "Severity::Warning".id : "Severity::Refactoring".id %}
 | 
				
			||||||
 | 
					        {% properties["severity".id] = {key: "Severity", default: default, type: Severity, converter: SeverityYamlConverter} %}
 | 
				
			||||||
 | 
					      {% end %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {% if properties["excluded".id] == nil %}
 | 
					      {% if properties["excluded".id] == nil %}
 | 
				
			||||||
        {% properties["excluded".id] = {key: "Excluded", type: "Array(String)?".id} %}
 | 
					        {% properties["excluded".id] = {key: "Excluded", type: "Array(String)?".id} %}
 | 
				
			||||||
      {% end %}
 | 
					      {% end %}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ module Ameba::Formatter
 | 
				
			||||||
          next if (location = issue.location).nil?
 | 
					          next if (location = issue.location).nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          output << "#{location}\n".colorize(:cyan)
 | 
					          output << "#{location}\n".colorize(:cyan)
 | 
				
			||||||
          output << "#{issue.rule.name}: #{issue.message}\n".colorize(:red)
 | 
					          output << "[#{issue.rule.severity.symbol}] #{issue.rule.name}: #{issue.message}\n".colorize(:red)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if show_affected_code && (code = affected_code(source, location))
 | 
					          if show_affected_code && (code = affected_code(source, location))
 | 
				
			||||||
            output << code
 | 
					            output << code
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ module Ameba::Formatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if rule.responds_to?(:description)
 | 
					      if rule.responds_to?(:description)
 | 
				
			||||||
        output_title "RULE INFO"
 | 
					        output_title "RULE INFO"
 | 
				
			||||||
        output_paragraph [rule.name, rule.description]
 | 
					        output_paragraph [rule.severity.to_s, rule.name, rule.description]
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      output_title "DETAILED DESCRIPTION"
 | 
					      output_title "DETAILED DESCRIPTION"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ module Ameba::Formatter
 | 
				
			||||||
        next if e.disabled?
 | 
					        next if e.disabled?
 | 
				
			||||||
        if loc = e.location
 | 
					        if loc = e.location
 | 
				
			||||||
          output.printf "%s:%d:%d: %s: [%s] %s\n",
 | 
					          output.printf "%s:%d:%d: %s: [%s] %s\n",
 | 
				
			||||||
            source.path, loc.line_number, loc.column_number, "E",
 | 
					            source.path, loc.line_number, loc.column_number, e.rule.severity.symbol,
 | 
				
			||||||
            e.rule.name, e.message.gsub("\n", " ")
 | 
					            e.rule.name, e.message.gsub("\n", " ")
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ module Ameba::Formatter
 | 
				
			||||||
  #           },
 | 
					  #           },
 | 
				
			||||||
  #           "message":   "Useless assignment to variable `a`",
 | 
					  #           "message":   "Useless assignment to variable `a`",
 | 
				
			||||||
  #           "rule_name": "UselessAssign",
 | 
					  #           "rule_name": "UselessAssign",
 | 
				
			||||||
 | 
					  #           "severity":  "Refactoring",
 | 
				
			||||||
  #         },
 | 
					  #         },
 | 
				
			||||||
  #         {
 | 
					  #         {
 | 
				
			||||||
  #           "location": {
 | 
					  #           "location": {
 | 
				
			||||||
| 
						 | 
					@ -49,6 +50,7 @@ module Ameba::Formatter
 | 
				
			||||||
  #           },
 | 
					  #           },
 | 
				
			||||||
  #           "message":   "Useless assignment to variable `a`",
 | 
					  #           "message":   "Useless assignment to variable `a`",
 | 
				
			||||||
  #           "rule_name": "UselessAssign",
 | 
					  #           "rule_name": "UselessAssign",
 | 
				
			||||||
 | 
					  #           "severity":  "Refactoring",
 | 
				
			||||||
  #         },
 | 
					  #         },
 | 
				
			||||||
  #       ],
 | 
					  #       ],
 | 
				
			||||||
  #       "path": "src/ameba/formatter/json_formatter.cr",
 | 
					  #       "path": "src/ameba/formatter/json_formatter.cr",
 | 
				
			||||||
| 
						 | 
					@ -75,7 +77,7 @@ module Ameba::Formatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      source.issues.each do |e|
 | 
					      source.issues.each do |e|
 | 
				
			||||||
        next if e.disabled?
 | 
					        next if e.disabled?
 | 
				
			||||||
        json_source.issues << AsJSON::Issue.new(e.rule.name, e.location, e.end_location, e.message)
 | 
					        json_source.issues << AsJSON::Issue.new(e.rule.name, e.rule.severity.to_s, e.location, e.end_location, e.message)
 | 
				
			||||||
        @result.summary.issues_count += 1
 | 
					        @result.summary.issues_count += 1
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,12 +109,14 @@ module Ameba::Formatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    record Issue,
 | 
					    record Issue,
 | 
				
			||||||
      rule_name : String,
 | 
					      rule_name : String,
 | 
				
			||||||
 | 
					      severity : String,
 | 
				
			||||||
      location : Crystal::Location?,
 | 
					      location : Crystal::Location?,
 | 
				
			||||||
      end_location : Crystal::Location?,
 | 
					      end_location : Crystal::Location?,
 | 
				
			||||||
      message : String do
 | 
					      message : String do
 | 
				
			||||||
      def to_json(json)
 | 
					      def to_json(json)
 | 
				
			||||||
        json.object do
 | 
					        json.object do
 | 
				
			||||||
          json.field :rule_name, rule_name
 | 
					          json.field :rule_name, rule_name
 | 
				
			||||||
 | 
					          json.field :severity, severity
 | 
				
			||||||
          json.field :message, message
 | 
					          json.field :message, message
 | 
				
			||||||
          json.field :location,
 | 
					          json.field :location,
 | 
				
			||||||
            {line: location.try &.line_number, column: location.try &.column_number}
 | 
					            {line: location.try &.line_number, column: location.try &.column_number}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,10 @@ module Ameba::Rule::Lint
 | 
				
			||||||
  # ```
 | 
					  # ```
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
  struct Syntax < Base
 | 
					  struct Syntax < Base
 | 
				
			||||||
    getter description = "Reports invalid Crystal syntax."
 | 
					    properties do
 | 
				
			||||||
 | 
					      description "Reports invalid Crystal syntax"
 | 
				
			||||||
 | 
					      severity Severity::Error
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test(source)
 | 
					    def test(source)
 | 
				
			||||||
      source.ast
 | 
					      source.ast
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,9 @@ module Ameba
 | 
				
			||||||
    # A list of sources to run inspection on.
 | 
					    # A list of sources to run inspection on.
 | 
				
			||||||
    getter sources : Array(Source)
 | 
					    getter sources : Array(Source)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # A level of severity to be reported.
 | 
				
			||||||
 | 
					    @severity : Severity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # A formatter to prepare report.
 | 
					    # A formatter to prepare report.
 | 
				
			||||||
    @formatter : Formatter::BaseFormatter
 | 
					    @formatter : Formatter::BaseFormatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +42,7 @@ module Ameba
 | 
				
			||||||
    def initialize(config : Config)
 | 
					    def initialize(config : Config)
 | 
				
			||||||
      @sources = config.sources
 | 
					      @sources = config.sources
 | 
				
			||||||
      @formatter = config.formatter
 | 
					      @formatter = config.formatter
 | 
				
			||||||
 | 
					      @severity = config.severity
 | 
				
			||||||
      @rules = config.rules.select(&.enabled).reject!(&.special?)
 | 
					      @rules = config.rules.select(&.enabled).reject!(&.special?)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @unneeded_disable_directive_rule =
 | 
					      @unneeded_disable_directive_rule =
 | 
				
			||||||
| 
						 | 
					@ -47,7 +51,7 @@ module Ameba
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # :nodoc:
 | 
					    # :nodoc:
 | 
				
			||||||
    protected def initialize(@rules, @sources, @formatter)
 | 
					    protected def initialize(@rules, @sources, @formatter, @severity)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Performs the inspection. Iterates through all sources and test it using
 | 
					    # Performs the inspection. Iterates through all sources and test it using
 | 
				
			||||||
| 
						 | 
					@ -98,7 +102,7 @@ module Ameba
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Indicates whether the last inspection successful or not.
 | 
					    # Indicates whether the last inspection successful or not.
 | 
				
			||||||
    # It returns true if no issues in sources found, false otherwise.
 | 
					    # It returns true if no issues matching severity in sources found, false otherwise.
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    # runner = Ameba::Runner.new config
 | 
					    # runner = Ameba::Runner.new config
 | 
				
			||||||
| 
						 | 
					@ -107,7 +111,9 @@ module Ameba
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    def success?
 | 
					    def success?
 | 
				
			||||||
      @sources.all? &.valid?
 | 
					      @sources.all? do |source|
 | 
				
			||||||
 | 
					        source.issues.none? { |issue| issue.rule.severity <= @severity }
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def check_unneeded_directives(source)
 | 
					    private def check_unneeded_directives(source)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								src/ameba/severity.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/ameba/severity.cr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					module Ameba
 | 
				
			||||||
 | 
					  enum Severity
 | 
				
			||||||
 | 
					    Error
 | 
				
			||||||
 | 
					    Warning
 | 
				
			||||||
 | 
					    Refactoring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Returns a symbol uniquely indicating severity.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # ```
 | 
				
			||||||
 | 
					    # Severity::Warning.symbol # => 'W'
 | 
				
			||||||
 | 
					    # ```
 | 
				
			||||||
 | 
					    def symbol
 | 
				
			||||||
 | 
					      to_s[0]
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Creates Severity by the name.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    # ```
 | 
				
			||||||
 | 
					    # Severity.from_name('refactoring') # => Severity::Refactoring
 | 
				
			||||||
 | 
					    # Severity.from_name('foo-bar')     # => Exception: Incorrect severity name..
 | 
				
			||||||
 | 
					    # ```
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
 | 
					    def self.from_name(name : String)
 | 
				
			||||||
 | 
					      parse(name)
 | 
				
			||||||
 | 
					    rescue ArgumentError
 | 
				
			||||||
 | 
					      raise "Incorrect severity name #{name}. Try one of #{Severity.values}"
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Converter for `YAML.mapping` which converts severity enum to and from YAML.
 | 
				
			||||||
 | 
					  class SeverityYamlConverter
 | 
				
			||||||
 | 
					    def self.from_yaml(ctx : YAML::ParseContext, node : YAML::Nodes::Node)
 | 
				
			||||||
 | 
					      unless node.is_a?(YAML::Nodes::Scalar)
 | 
				
			||||||
 | 
					        raise "Severity must be a scalar, not #{node.class}"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case value = node.value
 | 
				
			||||||
 | 
					      when String then Severity.from_name(value)
 | 
				
			||||||
 | 
					      when Nil    then nil
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        raise "Incorrect severity: #{value}"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def self.to_yaml(value : Severity, yaml : YAML::Nodes::Builder)
 | 
				
			||||||
 | 
					      yaml.scalar value
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue