mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	Misc refactors (#180)
* Optimize Severity#symbol * Remove empty else branches * Optimize map+compact/flatten calls * Misc stylistic refactors
This commit is contained in:
		
							parent
							
								
									9d85e731f5
								
							
						
					
					
						commit
						19c370aee0
					
				
					 20 changed files with 87 additions and 98 deletions
				
			
		| 
						 | 
					@ -37,8 +37,7 @@ module Ameba::AST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns true if this node or one of the parent branchables is a loop, false otherwise.
 | 
					    # Returns true if this node or one of the parent branchables is a loop, false otherwise.
 | 
				
			||||||
    def loop?
 | 
					    def loop?
 | 
				
			||||||
      return true if loop?(node)
 | 
					      loop?(node) || parent.try(&.loop?) || false
 | 
				
			||||||
      parent.try(&.loop?) || false
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,8 +59,6 @@ module Ameba::AST
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      when Crystal::BinaryOp
 | 
					      when Crystal::BinaryOp
 | 
				
			||||||
        unreachable_nodes << current_node.right if flow_expression?(current_node.left, in_loop?)
 | 
					        unreachable_nodes << current_node.right if flow_expression?(current_node.left, in_loop?)
 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        # nop
 | 
					 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      unreachable_nodes
 | 
					      unreachable_nodes
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,8 +117,8 @@ module Ameba::AST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns true instance variable assinged in this scope.
 | 
					    # Returns true instance variable assinged in this scope.
 | 
				
			||||||
    def assigns_ivar?(name)
 | 
					    def assigns_ivar?(name)
 | 
				
			||||||
      arguments.find { |arg| arg.name == name } &&
 | 
					      arguments.find(&.name.== name) &&
 | 
				
			||||||
        ivariables.find { |var| var.name == "@#{name}" }
 | 
					        ivariables.find(&.name.== "@#{name}")
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns true if and only if current scope represents some
 | 
					    # Returns true if and only if current scope represents some
 | 
				
			||||||
| 
						 | 
					@ -137,13 +137,13 @@ module Ameba::AST
 | 
				
			||||||
    def references?(variable : Variable)
 | 
					    def references?(variable : Variable)
 | 
				
			||||||
      variable.references.any? do |reference|
 | 
					      variable.references.any? do |reference|
 | 
				
			||||||
        reference.scope == self ||
 | 
					        reference.scope == self ||
 | 
				
			||||||
          inner_scopes.any?(&.references? variable)
 | 
					          inner_scopes.any?(&.references?(variable))
 | 
				
			||||||
      end || variable.used_in_macro?
 | 
					      end || variable.used_in_macro?
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns true if current scope is a def, false if not.
 | 
					    # Returns true if current scope is a def, false if not.
 | 
				
			||||||
    def def?
 | 
					    def def?
 | 
				
			||||||
      node.is_a? Crystal::Def
 | 
					      node.is_a?(Crystal::Def)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns true if this scope is a top level scope, false if not.
 | 
					    # Returns true if this scope is a top level scope, false if not.
 | 
				
			||||||
| 
						 | 
					@ -173,7 +173,7 @@ module Ameba::AST
 | 
				
			||||||
    # the same Crystal node as `@node`.
 | 
					    # the same Crystal node as `@node`.
 | 
				
			||||||
    def eql?(node)
 | 
					    def eql?(node)
 | 
				
			||||||
      node == @node &&
 | 
					      node == @node &&
 | 
				
			||||||
        !node.location.nil? &&
 | 
					        node.location &&
 | 
				
			||||||
        node.location == @node.location
 | 
					        node.location == @node.location
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,12 +72,12 @@ module Ameba::Cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      parser.on("--only RULE1,RULE2,...",
 | 
					      parser.on("--only RULE1,RULE2,...",
 | 
				
			||||||
        "Run only given rules (or groups)") do |rules|
 | 
					        "Run only given rules (or groups)") do |rules|
 | 
				
			||||||
        opts.only = rules.split ","
 | 
					        opts.only = rules.split(',')
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      parser.on("--except RULE1,RULE2,...",
 | 
					      parser.on("--except RULE1,RULE2,...",
 | 
				
			||||||
        "Disable the given rules (or groups)") do |rules|
 | 
					        "Disable the given rules (or groups)") do |rules|
 | 
				
			||||||
        opts.except = rules.split ","
 | 
					        opts.except = rules.split(',')
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      parser.on("--all", "Enables all available rules") do
 | 
					      parser.on("--all", "Enables all available rules") do
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,8 @@ module Ameba::Cli
 | 
				
			||||||
        opts.config = ""
 | 
					        opts.config = ""
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      parser.on("--fail-level SEVERITY", "Change the level of failure to exit. Defaults to Convention") do |level|
 | 
					      parser.on("--fail-level SEVERITY",
 | 
				
			||||||
 | 
					        "Change the level of failure to exit. Defaults to Convention") do |level|
 | 
				
			||||||
        opts.fail_level = Severity.parse(level)
 | 
					        opts.fail_level = Severity.parse(level)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,13 +114,13 @@ module Ameba::Cli
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private def configure_rules(config, opts)
 | 
					  private def configure_rules(config, opts)
 | 
				
			||||||
    if only = opts.only
 | 
					    case
 | 
				
			||||||
      config.rules.map! { |r| r.enabled = false; r }
 | 
					    when only = opts.only
 | 
				
			||||||
 | 
					      config.rules.map! &.tap(&.enabled = false)
 | 
				
			||||||
      config.update_rules(only, enabled: true)
 | 
					      config.update_rules(only, enabled: true)
 | 
				
			||||||
    elsif opts.all?
 | 
					    when opts.all?
 | 
				
			||||||
      config.rules.map! { |r| r.enabled = true; r }
 | 
					      config.rules.map! &.tap(&.enabled = true)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					 | 
				
			||||||
    config.update_rules(opts.except, enabled: false)
 | 
					    config.update_rules(opts.except, enabled: false)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,7 +128,8 @@ module Ameba::Cli
 | 
				
			||||||
    if name = opts.formatter
 | 
					    if name = opts.formatter
 | 
				
			||||||
      config.formatter = name
 | 
					      config.formatter = name
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
    config.formatter.config[:without_affected_code] = opts.without_affected_code?
 | 
					    config.formatter.config[:without_affected_code] =
 | 
				
			||||||
 | 
					      opts.without_affected_code?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private def configure_explain_opts(loc, opts)
 | 
					  private def configure_explain_opts(loc, opts)
 | 
				
			||||||
| 
						 | 
					@ -138,10 +140,15 @@ module Ameba::Cli
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private def parse_explain_location(arg)
 | 
					  private def parse_explain_location(arg)
 | 
				
			||||||
    location = arg.split(":", remove_empty: true).map &.strip
 | 
					    location = arg.split(':', remove_empty: true).map! &.strip
 | 
				
			||||||
    raise ArgumentError.new unless location.size === 3
 | 
					    raise ArgumentError.new unless location.size === 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    file, line, column = location
 | 
					    file, line, column = location
 | 
				
			||||||
    {file: file, line: line.to_i, column: column.to_i}
 | 
					    {
 | 
				
			||||||
 | 
					      file:   file,
 | 
				
			||||||
 | 
					      line:   line.to_i,
 | 
				
			||||||
 | 
					      column: column.to_i,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  rescue
 | 
					  rescue
 | 
				
			||||||
    raise "location should have PATH:line:column format"
 | 
					    raise "location should have PATH:line:column format"
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,6 @@ class Ameba::Config
 | 
				
			||||||
    !lib
 | 
					    !lib
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  setter formatter : Formatter::BaseFormatter?
 | 
					 | 
				
			||||||
  getter rules : Array(Rule::Base)
 | 
					  getter rules : Array(Rule::Base)
 | 
				
			||||||
  property severity = Severity::Convention
 | 
					  property severity = Severity::Convention
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,7 +65,9 @@ class Ameba::Config
 | 
				
			||||||
    @excluded = load_array_section(config, "Excluded")
 | 
					    @excluded = load_array_section(config, "Excluded")
 | 
				
			||||||
    @globs = load_array_section(config, "Globs", DEFAULT_GLOBS)
 | 
					    @globs = load_array_section(config, "Globs", DEFAULT_GLOBS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self.formatter = load_formatter_name(config)
 | 
					    if formatter_name = load_formatter_name(config)
 | 
				
			||||||
 | 
					      self.formatter = formatter_name
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Loads YAML configuration file by `path`.
 | 
					  # Loads YAML configuration file by `path`.
 | 
				
			||||||
| 
						 | 
					@ -84,7 +85,7 @@ class Ameba::Config
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def self.formatter_names
 | 
					  def self.formatter_names
 | 
				
			||||||
    AVAILABLE_FORMATTERS.keys.join("|")
 | 
					    AVAILABLE_FORMATTERS.keys.join('|')
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Returns a list of sources matching globs and excluded sections.
 | 
					  # Returns a list of sources matching globs and excluded sections.
 | 
				
			||||||
| 
						 | 
					@ -111,8 +112,8 @@ class Ameba::Config
 | 
				
			||||||
  # config.formatter
 | 
					  # config.formatter
 | 
				
			||||||
  # ```
 | 
					  # ```
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
  def formatter
 | 
					  property formatter : Formatter::BaseFormatter do
 | 
				
			||||||
    @formatter ||= Formatter::DotFormatter.new
 | 
					    Formatter::DotFormatter.new
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Sets formatter by name.
 | 
					  # Sets formatter by name.
 | 
				
			||||||
| 
						 | 
					@ -138,7 +139,7 @@ class Ameba::Config
 | 
				
			||||||
  # ```
 | 
					  # ```
 | 
				
			||||||
  #
 | 
					  #
 | 
				
			||||||
  def update_rule(name, enabled = true, excluded = nil)
 | 
					  def update_rule(name, enabled = true, excluded = nil)
 | 
				
			||||||
    index = @rules.index { |r| r.name == name }
 | 
					    index = @rules.index { |rule| rule.name == name }
 | 
				
			||||||
    raise ArgumentError.new("Rule `#{name}` does not exist") unless index
 | 
					    raise ArgumentError.new("Rule `#{name}` does not exist") unless index
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rule = @rules[index]
 | 
					    rule = @rules[index]
 | 
				
			||||||
| 
						 | 
					@ -172,7 +173,7 @@ class Ameba::Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private def load_formatter_name(config)
 | 
					  private def load_formatter_name(config)
 | 
				
			||||||
    name = config["Formatter"]?.try &.["Name"]?
 | 
					    name = config["Formatter"]?.try &.["Name"]?
 | 
				
			||||||
    name ? name.to_s : nil
 | 
					    name.try(&.to_s)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private def load_array_section(config, section_name, default = [] of String)
 | 
					  private def load_array_section(config, section_name, default = [] of String)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,14 +35,17 @@ module Ameba::Formatter
 | 
				
			||||||
          next if issue.disabled?
 | 
					          next if issue.disabled?
 | 
				
			||||||
          next if (location = issue.location).nil?
 | 
					          next if (location = issue.location).nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          output << "#{location}\n".colorize(:cyan)
 | 
					          output.puts location.colorize(:cyan)
 | 
				
			||||||
          output << "[#{issue.rule.severity.symbol}] #{issue.rule.name}: #{issue.message}\n".colorize(:red)
 | 
					          output.puts \
 | 
				
			||||||
 | 
					            "[#{issue.rule.severity.symbol}] " \
 | 
				
			||||||
 | 
					            "#{issue.rule.name}: " \
 | 
				
			||||||
 | 
					            "#{issue.message}".colorize(:red)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if show_affected_code && (code = affected_code(source, location))
 | 
					          if show_affected_code && (code = affected_code(source, location))
 | 
				
			||||||
            output << code.colorize(:default)
 | 
					            output << code.colorize(:default)
 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          output << "\n"
 | 
					          output << '\n'
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,9 +4,8 @@ module Ameba::Formatter
 | 
				
			||||||
  # A formatter that shows the detailed explanation of the issue at
 | 
					  # A formatter that shows the detailed explanation of the issue at
 | 
				
			||||||
  # a specific location.
 | 
					  # a specific location.
 | 
				
			||||||
  class ExplainFormatter
 | 
					  class ExplainFormatter
 | 
				
			||||||
    LINE_BREAK = "\n"
 | 
					    HEADING = "## "
 | 
				
			||||||
    HEADING    = "## "
 | 
					    PREFIX  = " "
 | 
				
			||||||
    PREFIX     = " "
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    include Util
 | 
					    include Util
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,19 +64,19 @@ module Ameba::Formatter
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def output_title(title)
 | 
					    private def output_title(title)
 | 
				
			||||||
      output << HEADING.colorize(:yellow) << title.colorize(:yellow) << LINE_BREAK
 | 
					      output << HEADING.colorize(:yellow) << title.colorize(:yellow) << '\n'
 | 
				
			||||||
      output << LINE_BREAK
 | 
					      output << '\n'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def output_paragraph(paragraph : String)
 | 
					    private def output_paragraph(paragraph : String)
 | 
				
			||||||
      output_paragraph(paragraph.split(LINE_BREAK))
 | 
					      output_paragraph(paragraph.split('\n'))
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def output_paragraph(paragraph : Array(String))
 | 
					    private def output_paragraph(paragraph : Array(String))
 | 
				
			||||||
      paragraph.each do |line|
 | 
					      paragraph.each do |line|
 | 
				
			||||||
        output << PREFIX << line << LINE_BREAK
 | 
					        output << PREFIX << line << '\n'
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
      output << LINE_BREAK
 | 
					      output << '\n'
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ module Ameba::Formatter
 | 
				
			||||||
          @mutex.synchronize do
 | 
					          @mutex.synchronize do
 | 
				
			||||||
            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.rule.severity.symbol,
 | 
					              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
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,19 +8,20 @@ module Ameba::Formatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def finished(sources)
 | 
					    def finished(sources)
 | 
				
			||||||
      super
 | 
					      super
 | 
				
			||||||
      issues = sources.map(&.issues).flatten
 | 
					
 | 
				
			||||||
 | 
					      issues = sources.flat_map(&.issues)
 | 
				
			||||||
      unless issues.any? { |issue| !issue.disabled? }
 | 
					      unless issues.any? { |issue| !issue.disabled? }
 | 
				
			||||||
        @output << "No issues found. File is not generated.\n"
 | 
					        @output.puts "No issues found. File is not generated."
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if issues.any? { |issue| issue.syntax? }
 | 
					      if issues.any?(&.syntax?)
 | 
				
			||||||
        @output << "Unable to generate TODO file. Please fix syntax issues.\n"
 | 
					        @output.puts "Unable to generate TODO file. Please fix syntax issues."
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      file = generate_todo_config issues
 | 
					      file = generate_todo_config issues
 | 
				
			||||||
      @output << "Created #{file.path}\n"
 | 
					      @output.puts "Created #{file.path}"
 | 
				
			||||||
      file
 | 
					      file
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,10 +58,9 @@ module Ameba::Formatter
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def rule_todo(rule, issues)
 | 
					    private def rule_todo(rule, issues)
 | 
				
			||||||
      rule.excluded =
 | 
					      rule.excluded = issues
 | 
				
			||||||
        issues.map(&.location.try &.filename.try &.to_s)
 | 
					        .compact_map(&.location.try &.filename.try &.to_s)
 | 
				
			||||||
          .compact
 | 
					        .uniq!
 | 
				
			||||||
          .uniq!
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {rule.name => rule}.to_yaml
 | 
					      {rule.name => rule}.to_yaml
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,9 @@ module Ameba::Formatter
 | 
				
			||||||
  module Util
 | 
					  module Util
 | 
				
			||||||
    def affected_code(source, location, max_length = 100, placeholder = " ...", prompt = "> ")
 | 
					    def affected_code(source, location, max_length = 100, placeholder = " ...", prompt = "> ")
 | 
				
			||||||
      line, column = location.line_number, location.column_number
 | 
					      line, column = location.line_number, location.column_number
 | 
				
			||||||
      affected_line = source.lines[line - 1]?
 | 
					      affected_line = source.lines[line - 1]?.presence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return if affected_line.nil? || affected_line.strip.empty?
 | 
					      return unless affected_line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if affected_line.size > max_length && column < max_length
 | 
					      if affected_line.size > max_length && column < max_length
 | 
				
			||||||
        affected_line = affected_line[0, max_length - placeholder.size - 1] + placeholder
 | 
					        affected_line = affected_line[0, max_length - placeholder.size - 1] + placeholder
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ module Ameba::Formatter
 | 
				
			||||||
      position = column - (affected_line.size - stripped.size) + prompt.size
 | 
					      position = column - (affected_line.size - stripped.size) + prompt.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      String.build do |str|
 | 
					      String.build do |str|
 | 
				
			||||||
        str << prompt << stripped << "\n"
 | 
					        str << prompt << stripped << '\n'
 | 
				
			||||||
        str << " " * (position - 1)
 | 
					        str << " " * (position - 1)
 | 
				
			||||||
        str << "^".colorize(:yellow)
 | 
					        str << "^".colorize(:yellow)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,10 +22,10 @@ module Ameba
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    def expand(globs)
 | 
					    def expand(globs)
 | 
				
			||||||
      globs.map do |glob|
 | 
					      globs.flat_map do |glob|
 | 
				
			||||||
        glob += "/**/*.cr" if File.directory?(glob)
 | 
					        glob += "/**/*.cr" if File.directory?(glob)
 | 
				
			||||||
        Dir[glob]
 | 
					        Dir[glob]
 | 
				
			||||||
      end.flatten.uniq!
 | 
					      end.uniq!
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def rejected_globs(globs)
 | 
					    private def rejected_globs(globs)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,8 +89,10 @@ module Ameba
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def line_disabled?(line, rule)
 | 
					    private def line_disabled?(line, rule)
 | 
				
			||||||
      return false unless directive = parse_inline_directive(line)
 | 
					      return false unless directive = parse_inline_directive(line)
 | 
				
			||||||
      Action.parse?(directive[:action]).try(&.disable?) &&
 | 
					      return false unless Action.parse?(directive[:action]).try(&.disable?)
 | 
				
			||||||
        (directive[:rules].includes?(rule.name) || directive[:rules].includes?(rule.group))
 | 
					
 | 
				
			||||||
 | 
					      directive[:rules].includes?(rule.name) ||
 | 
				
			||||||
 | 
					        directive[:rules].includes?(rule.group)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def commented_out?(line)
 | 
					    private def commented_out?(line)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,7 @@ module Ameba::Rule
 | 
				
			||||||
    def excluded?(source)
 | 
					    def excluded?(source)
 | 
				
			||||||
      excluded.try &.any? do |path|
 | 
					      excluded.try &.any? do |path|
 | 
				
			||||||
        source.matches_path?(path) ||
 | 
					        source.matches_path?(path) ||
 | 
				
			||||||
          Dir.glob(path).any? { |glob| source.matches_path? glob }
 | 
					          Dir.glob(path).any? { |glob| source.matches_path?(glob) }
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,11 +123,11 @@ module Ameba::Rule
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected def self.rule_name
 | 
					    protected def self.rule_name
 | 
				
			||||||
      name.gsub("Ameba::Rule::", "").gsub("::", "/")
 | 
					      name.gsub("Ameba::Rule::", "").gsub("::", '/')
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected def self.group_name
 | 
					    protected def self.group_name
 | 
				
			||||||
      rule_name.split("/")[0...-1].join("/")
 | 
					      rule_name.split('/')[0...-1].join('/')
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected def self.subclasses
 | 
					    protected def self.subclasses
 | 
				
			||||||
| 
						 | 
					@ -157,7 +157,7 @@ module Ameba::Rule
 | 
				
			||||||
    def self.parsed_doc
 | 
					    def self.parsed_doc
 | 
				
			||||||
      source = File.read(path_to_source_file)
 | 
					      source = File.read(path_to_source_file)
 | 
				
			||||||
      nodes = Crystal::Parser.new(source).tap(&.wants_doc = true).parse
 | 
					      nodes = Crystal::Parser.new(source).tap(&.wants_doc = true).parse
 | 
				
			||||||
      type_name = rule_name.split("/").last?
 | 
					      type_name = rule_name.split('/').last?
 | 
				
			||||||
      DocFinder.new(nodes, type_name).doc
 | 
					      DocFinder.new(nodes, type_name).doc
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,8 +49,6 @@ module Ameba::Rule::Lint
 | 
				
			||||||
            issue_for start_token.not_nil!, issue.not_nil!
 | 
					            issue_for start_token.not_nil!, issue.not_nil!
 | 
				
			||||||
          end
 | 
					          end
 | 
				
			||||||
          issue = start_token = nil
 | 
					          issue = start_token = nil
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          # nop
 | 
					 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -61,8 +59,6 @@ module Ameba::Rule::Lint
 | 
				
			||||||
        check_array_entry entry, string_array_unwanted_symbols, "%w"
 | 
					        check_array_entry entry, string_array_unwanted_symbols, "%w"
 | 
				
			||||||
      when .starts_with? "%i"
 | 
					      when .starts_with? "%i"
 | 
				
			||||||
        check_array_entry entry, symbol_array_unwanted_symbols, "%i"
 | 
					        check_array_entry entry, symbol_array_unwanted_symbols, "%i"
 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        # nop
 | 
					 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,8 +42,6 @@ module Ameba::Rule::Lint
 | 
				
			||||||
        report source, node, "Remove redundant with_index"
 | 
					        report source, node, "Remove redundant with_index"
 | 
				
			||||||
      when "each_with_index"
 | 
					      when "each_with_index"
 | 
				
			||||||
        report source, node, "Use each instead of each_with_index"
 | 
					        report source, node, "Use each instead of each_with_index"
 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        # nop
 | 
					 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,8 +76,6 @@ module Ameba::Rule::Style
 | 
				
			||||||
        redundant_begin_in_handler?(source, body, node)
 | 
					        redundant_begin_in_handler?(source, body, node)
 | 
				
			||||||
      when Crystal::Expressions
 | 
					      when Crystal::Expressions
 | 
				
			||||||
        redundant_begin_in_expressions?(body)
 | 
					        redundant_begin_in_expressions?(body)
 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
        # nop
 | 
					 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +86,7 @@ module Ameba::Rule::Style
 | 
				
			||||||
    private def redundant_begin_in_handler?(source, handler, node)
 | 
					    private def redundant_begin_in_handler?(source, handler, node)
 | 
				
			||||||
      return false if begin_exprs_in_handler?(handler) || inner_handler?(handler)
 | 
					      return false if begin_exprs_in_handler?(handler) || inner_handler?(handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      code = node_source(node, source.lines).try &.join("\n")
 | 
					      code = node_source(node, source.lines).try &.join('\n')
 | 
				
			||||||
      def_redundant_begin? code if code
 | 
					      def_redundant_begin? code if code
 | 
				
			||||||
    rescue
 | 
					    rescue
 | 
				
			||||||
      false
 | 
					      false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,6 @@ module Ameba
 | 
				
			||||||
          .find &.name.==(Rule::Lint::UnneededDisableDirective.rule_name)
 | 
					          .find &.name.==(Rule::Lint::UnneededDisableDirective.rule_name)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # :nodoc:
 | 
					 | 
				
			||||||
    protected def initialize(@rules, @sources, @formatter, @severity)
 | 
					    protected def initialize(@rules, @sources, @formatter, @severity)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,9 +79,8 @@ module Ameba
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      channels.each do |c|
 | 
					      channels.each do |chan|
 | 
				
			||||||
        e = c.receive
 | 
					        chan.receive.try { |e| raise e }
 | 
				
			||||||
        raise e unless e.nil?
 | 
					 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      self
 | 
					      self
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,8 +9,12 @@ module Ameba
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    # Severity::Warning.symbol # => 'W'
 | 
					    # Severity::Warning.symbol # => 'W'
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    def symbol
 | 
					    def symbol : Char
 | 
				
			||||||
      to_s[0]
 | 
					      case self
 | 
				
			||||||
 | 
					      in Error      then 'E'
 | 
				
			||||||
 | 
					      in Warning    then 'W'
 | 
				
			||||||
 | 
					      in Convention then 'C'
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Creates Severity by the name.
 | 
					    # Creates Severity by the name.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,10 +11,6 @@ module Ameba
 | 
				
			||||||
    # Crystal code (content of a source file).
 | 
					    # Crystal code (content of a source file).
 | 
				
			||||||
    getter code : String
 | 
					    getter code : String
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @lines : Array(String)?
 | 
					 | 
				
			||||||
    @ast : Crystal::ASTNode?
 | 
					 | 
				
			||||||
    @fullpath : String?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Creates a new source by `code` and `path`.
 | 
					    # Creates a new source by `code` and `path`.
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # For example:
 | 
					    # For example:
 | 
				
			||||||
| 
						 | 
					@ -24,7 +20,7 @@ module Ameba
 | 
				
			||||||
    # Ameba::Source.new File.read(path), path
 | 
					    # Ameba::Source.new File.read(path), path
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    def initialize(@code : String, @path = "")
 | 
					    def initialize(@code, @path = "")
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns lines of code splitted by new line character.
 | 
					    # Returns lines of code splitted by new line character.
 | 
				
			||||||
| 
						 | 
					@ -38,9 +34,7 @@ module Ameba
 | 
				
			||||||
    # source.lines # => ["a = 1", "b = 2"]
 | 
					    # source.lines # => ["a = 1", "b = 2"]
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    def lines
 | 
					    getter lines : Array(String) { code.split('\n') }
 | 
				
			||||||
      @lines ||= @code.split("\n")
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns AST nodes constructed by `Crystal::Parser`.
 | 
					    # Returns AST nodes constructed by `Crystal::Parser`.
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
| 
						 | 
					@ -49,16 +43,15 @@ module Ameba
 | 
				
			||||||
    # source.ast
 | 
					    # source.ast
 | 
				
			||||||
    # ```
 | 
					    # ```
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    def ast
 | 
					    getter ast : Crystal::ASTNode do
 | 
				
			||||||
      @ast ||=
 | 
					      Crystal::Parser.new(code)
 | 
				
			||||||
        Crystal::Parser.new(code)
 | 
					        .tap(&.wants_doc = true)
 | 
				
			||||||
          .tap { |parser| parser.wants_doc = true }
 | 
					        .tap(&.filename = path)
 | 
				
			||||||
          .tap { |parser| parser.filename = @path }
 | 
					        .parse
 | 
				
			||||||
          .parse
 | 
					 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def fullpath
 | 
					    getter fullpath : String do
 | 
				
			||||||
      @fullpath ||= File.expand_path @path
 | 
					      File.expand_path(path)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Returns true if *filepath* matches the source's path, false if it does not.
 | 
					    # Returns true if *filepath* matches the source's path, false if it does not.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,8 +53,7 @@ module Ameba
 | 
				
			||||||
      false
 | 
					      false
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private def run_normal_state(lexer, break_on_rcurly = false,
 | 
					    private def run_normal_state(lexer, break_on_rcurly = false, &block : Crystal::Token -> _)
 | 
				
			||||||
                                 &block : Crystal::Token -> _)
 | 
					 | 
				
			||||||
      loop do
 | 
					      loop do
 | 
				
			||||||
        token = @lexer.next_token
 | 
					        token = @lexer.next_token
 | 
				
			||||||
        block.call token
 | 
					        block.call token
 | 
				
			||||||
| 
						 | 
					@ -68,8 +67,6 @@ module Ameba
 | 
				
			||||||
          break
 | 
					          break
 | 
				
			||||||
        when :"}"
 | 
					        when :"}"
 | 
				
			||||||
          break if break_on_rcurly
 | 
					          break if break_on_rcurly
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          # go on
 | 
					 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -86,8 +83,6 @@ module Ameba
 | 
				
			||||||
          run_normal_state lexer, break_on_rcurly: true, &block
 | 
					          run_normal_state lexer, break_on_rcurly: true, &block
 | 
				
			||||||
        when :EOF
 | 
					        when :EOF
 | 
				
			||||||
          break
 | 
					          break
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          # go on
 | 
					 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					@ -102,8 +97,6 @@ module Ameba
 | 
				
			||||||
          break
 | 
					          break
 | 
				
			||||||
        when :EOF
 | 
					        when :EOF
 | 
				
			||||||
          break
 | 
					          break
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          # go on
 | 
					 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue