mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	Add JSON formatter
This commit is contained in:
		
							parent
							
								
									9708b94587
								
							
						
					
					
						commit
						4546b90b54
					
				
					 3 changed files with 212 additions and 0 deletions
				
			
		
							
								
								
									
										78
									
								
								spec/ameba/formatter/json_formatter_spec.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								spec/ameba/formatter/json_formatter_spec.cr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,78 @@
 | 
				
			||||||
 | 
					require "../../spec_helper"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Ameba
 | 
				
			||||||
 | 
					  def get_result(sources = [Source.new ""])
 | 
				
			||||||
 | 
					    file = IO::Memory.new
 | 
				
			||||||
 | 
					    formatter = Formatter::JSONFormatter.new file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    formatter.started sources
 | 
				
			||||||
 | 
					    sources.each { |source| formatter.source_finished source }
 | 
				
			||||||
 | 
					    formatter.finished sources
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    JSON.parse file.to_s
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe Formatter::JSONFormatter do
 | 
				
			||||||
 | 
					    context "metadata" do
 | 
				
			||||||
 | 
					      it "shows ameba version" do
 | 
				
			||||||
 | 
					        get_result["metadata"]["ameba_version"].should eq Ameba::VERSION
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "shows crystal version" do
 | 
				
			||||||
 | 
					        get_result["metadata"]["crystal_version"].should eq Crystal::VERSION
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context "sources" do
 | 
				
			||||||
 | 
					      it "shows path to the source" do
 | 
				
			||||||
 | 
					        result = get_result [Source.new "", "source.cr"]
 | 
				
			||||||
 | 
					        result["sources"].first["path"].should eq "source.cr"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "shows rule name" do
 | 
				
			||||||
 | 
					        s = Source.new ""
 | 
				
			||||||
 | 
					        s.error DummyRule.new, 1, 2, "message1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = get_result [s]
 | 
				
			||||||
 | 
					        result["sources"].first["errors"].first["rule_name"].should eq DummyRule.name
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "shows a message" do
 | 
				
			||||||
 | 
					        s = Source.new ""
 | 
				
			||||||
 | 
					        s.error DummyRule.new, 1, 2, "message"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = get_result [s]
 | 
				
			||||||
 | 
					        result["sources"].first["errors"].first["message"].should eq "message"
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "shows error location" do
 | 
				
			||||||
 | 
					        s = Source.new ""
 | 
				
			||||||
 | 
					        s.error DummyRule.new, 1, 2, "message"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = get_result [s]
 | 
				
			||||||
 | 
					        location = result["sources"].first["errors"].first["location"]
 | 
				
			||||||
 | 
					        location["line"].should eq 1
 | 
				
			||||||
 | 
					        location["column"].should eq 2
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context "summary" do
 | 
				
			||||||
 | 
					      it "shows a target sources count" do
 | 
				
			||||||
 | 
					        result = get_result [Source.new(""), Source.new("")]
 | 
				
			||||||
 | 
					        result["summary"]["target_sources_count"].should eq 2
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it "shows errors count" do
 | 
				
			||||||
 | 
					        s1 = Source.new ""
 | 
				
			||||||
 | 
					        s1.error DummyRule.new, 1, 2, "message1"
 | 
				
			||||||
 | 
					        s1.error DummyRule.new, 1, 2, "message2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s2 = Source.new ""
 | 
				
			||||||
 | 
					        s2.error DummyRule.new, 1, 2, "message3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = get_result [s1, s2]
 | 
				
			||||||
 | 
					        result["summary"]["errors_count"].should eq 3
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ class Ameba::Config
 | 
				
			||||||
    flycheck: Formatter::FlycheckFormatter,
 | 
					    flycheck: Formatter::FlycheckFormatter,
 | 
				
			||||||
    silent:   Formatter::BaseFormatter,
 | 
					    silent:   Formatter::BaseFormatter,
 | 
				
			||||||
    disabled: Formatter::DisabledFormatter,
 | 
					    disabled: Formatter::DisabledFormatter,
 | 
				
			||||||
 | 
					    json:     Formatter::JSONFormatter,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PATH = ".ameba.yml"
 | 
					  PATH = ".ameba.yml"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										133
									
								
								src/ameba/formatter/json_formatter.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/ameba/formatter/json_formatter.cr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,133 @@
 | 
				
			||||||
 | 
					require "json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Ameba::Formatter
 | 
				
			||||||
 | 
					  # A formatter that produces the result in a json format.
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Example:
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # ```
 | 
				
			||||||
 | 
					  # {
 | 
				
			||||||
 | 
					  #   "metadata": {
 | 
				
			||||||
 | 
					  #     "ameba_version":   "x.x.x",
 | 
				
			||||||
 | 
					  #     "crystal_version": "x.x.x",
 | 
				
			||||||
 | 
					  #   },
 | 
				
			||||||
 | 
					  #   "sources": [
 | 
				
			||||||
 | 
					  #     {
 | 
				
			||||||
 | 
					  #       "errors": [
 | 
				
			||||||
 | 
					  #         {
 | 
				
			||||||
 | 
					  #           "location": {
 | 
				
			||||||
 | 
					  #             "column": 7,
 | 
				
			||||||
 | 
					  #             "line":   17,
 | 
				
			||||||
 | 
					  #           },
 | 
				
			||||||
 | 
					  #           "message":   "Useless assignment to variable `a`",
 | 
				
			||||||
 | 
					  #           "rule_name": "UselessAssign",
 | 
				
			||||||
 | 
					  #         },
 | 
				
			||||||
 | 
					  #         {
 | 
				
			||||||
 | 
					  #           "location": {
 | 
				
			||||||
 | 
					  #             "column": 7,
 | 
				
			||||||
 | 
					  #             "line":   18,
 | 
				
			||||||
 | 
					  #           },
 | 
				
			||||||
 | 
					  #           "message":   "Useless assignment to variable `a`",
 | 
				
			||||||
 | 
					  #           "rule_name": "UselessAssign",
 | 
				
			||||||
 | 
					  #         },
 | 
				
			||||||
 | 
					  #         {
 | 
				
			||||||
 | 
					  #           "location": {
 | 
				
			||||||
 | 
					  #             "column": 7,
 | 
				
			||||||
 | 
					  #             "line":   19,
 | 
				
			||||||
 | 
					  #           },
 | 
				
			||||||
 | 
					  #           "message":   "Useless assignment to variable `a`",
 | 
				
			||||||
 | 
					  #           "rule_name": "UselessAssign",
 | 
				
			||||||
 | 
					  #         },
 | 
				
			||||||
 | 
					  #       ],
 | 
				
			||||||
 | 
					  #       "path": "src/ameba/formatter/json_formatter.cr",
 | 
				
			||||||
 | 
					  #     },
 | 
				
			||||||
 | 
					  #   ],
 | 
				
			||||||
 | 
					  #   "summary": {
 | 
				
			||||||
 | 
					  #     "errors_count":         3,
 | 
				
			||||||
 | 
					  #     "target_sources_count": 1,
 | 
				
			||||||
 | 
					  #   },
 | 
				
			||||||
 | 
					  # }
 | 
				
			||||||
 | 
					  # ```
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  class JSONFormatter < BaseFormatter
 | 
				
			||||||
 | 
					    def initialize(@output = STDOUT)
 | 
				
			||||||
 | 
					      @result = AsJSON::Result.new
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def started(sources)
 | 
				
			||||||
 | 
					      @result.summary.target_sources_count = sources.size
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def source_finished(source : Source)
 | 
				
			||||||
 | 
					      json_source = AsJSON::Source.new source.path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      source.errors.each do |e|
 | 
				
			||||||
 | 
					        next if e.disabled?
 | 
				
			||||||
 | 
					        json_source.errors << AsJSON::Error.new(e.rule.name, e.location, e.message)
 | 
				
			||||||
 | 
					        @result.summary.errors_count += 1
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      @result.sources << json_source
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def finished(sources)
 | 
				
			||||||
 | 
					      @result.to_json @output
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private module AsJSON
 | 
				
			||||||
 | 
					    record Result,
 | 
				
			||||||
 | 
					      sources = [] of Source,
 | 
				
			||||||
 | 
					      metadata = Metadata.new,
 | 
				
			||||||
 | 
					      summary = Summary.new do
 | 
				
			||||||
 | 
					      def to_json(json)
 | 
				
			||||||
 | 
					        {sources: sources, metadata: metadata, summary: summary}.to_json(json)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    record Source,
 | 
				
			||||||
 | 
					      path : String,
 | 
				
			||||||
 | 
					      errors = [] of Error do
 | 
				
			||||||
 | 
					      def to_json(json)
 | 
				
			||||||
 | 
					        {path: path, errors: errors}.to_json(json)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    record Error,
 | 
				
			||||||
 | 
					      rule_name : String,
 | 
				
			||||||
 | 
					      location : Crystal::Location?,
 | 
				
			||||||
 | 
					      message : String do
 | 
				
			||||||
 | 
					      def to_json(json)
 | 
				
			||||||
 | 
					        json.object do
 | 
				
			||||||
 | 
					          json.field :rule_name, rule_name
 | 
				
			||||||
 | 
					          json.field :message, message
 | 
				
			||||||
 | 
					          json.field :location,
 | 
				
			||||||
 | 
					            {line: location.try &.line_number, column: location.try &.column_number}
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    record Metadata,
 | 
				
			||||||
 | 
					      ameba_version : String = Ameba::VERSION,
 | 
				
			||||||
 | 
					      crystal_version : String = Crystal::VERSION do
 | 
				
			||||||
 | 
					      def to_json(json)
 | 
				
			||||||
 | 
					        json.object do
 | 
				
			||||||
 | 
					          json.field :ameba_version, ameba_version
 | 
				
			||||||
 | 
					          json.field :crystal_version, crystal_version
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Summary
 | 
				
			||||||
 | 
					      property target_sources_count = 0
 | 
				
			||||||
 | 
					      property errors_count = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      def to_json(json)
 | 
				
			||||||
 | 
					        json.object do
 | 
				
			||||||
 | 
					          json.field :target_sources_count, target_sources_count
 | 
				
			||||||
 | 
					          json.field :errors_count, errors_count
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue