mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	Merge pull request #293 from crystal-ameba/Sija/refactor-static-comparison-rule
This commit is contained in:
		
						commit
						816c8b11cd
					
				
					 2 changed files with 36 additions and 12 deletions
				
			
		|  | @ -1,9 +1,9 @@ | ||||||
| require "../../../spec_helper" | require "../../../spec_helper" | ||||||
| 
 | 
 | ||||||
| module Ameba::Rule::Lint | module Ameba::Rule::Lint | ||||||
|   subject = StaticComparison.new |   subject = LiteralsComparison.new | ||||||
| 
 | 
 | ||||||
|   describe StaticComparison do |   describe LiteralsComparison do | ||||||
|     it "passes for valid cases" do |     it "passes for valid cases" do | ||||||
|       expect_no_issues subject, <<-CRYSTAL |       expect_no_issues subject, <<-CRYSTAL | ||||||
|         "foo" == foo |         "foo" == foo | ||||||
|  | @ -13,6 +13,13 @@ module Ameba::Rule::Lint | ||||||
|         CRYSTAL |         CRYSTAL | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |     it "reports if there is a regex comparison possibly evaluating to the same" do | ||||||
|  |       expect_issue subject, <<-CRYSTAL | ||||||
|  |         /foo/ === "foo" | ||||||
|  |         # ^^^^^^^^^^^^^ error: Comparison most likely evaluates to the same | ||||||
|  |         CRYSTAL | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|     it "reports if there is a static comparison evaluating to the same" do |     it "reports if there is a static comparison evaluating to the same" do | ||||||
|       expect_issue subject, <<-CRYSTAL |       expect_issue subject, <<-CRYSTAL | ||||||
|         "foo" === "foo" |         "foo" === "foo" | ||||||
|  | @ -1,6 +1,9 @@ | ||||||
| module Ameba::Rule::Lint | module Ameba::Rule::Lint | ||||||
|   # This rule is used to identify static comparisons - |   # This rule is used to identify comparisons between two literals. | ||||||
|   # the ones that will always have the same result. |   # | ||||||
|  |   # They usually have the same result - except for non-primitive | ||||||
|  |   # types like containers, range or regex. | ||||||
|  |   # | ||||||
|   # |   # | ||||||
|   # For example, this will be always false: |   # For example, this will be always false: | ||||||
|   # |   # | ||||||
|  | @ -11,39 +14,53 @@ module Ameba::Rule::Lint | ||||||
|   # YAML configuration example: |   # YAML configuration example: | ||||||
|   # |   # | ||||||
|   # ``` |   # ``` | ||||||
|   # Lint/StaticComparison: |   # Lint/LiteralsComparison: | ||||||
|   #   Enabled: true |   #   Enabled: true | ||||||
|   # ``` |   # ``` | ||||||
|   class StaticComparison < Base |   class LiteralsComparison < Base | ||||||
|     include AST::Util |     include AST::Util | ||||||
| 
 | 
 | ||||||
|     properties do |     properties do | ||||||
|       description "Identifies static comparisons" |       description "Identifies comparisons between literals" | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     OP_NAMES = %w(=== == !=) |     OP_NAMES = %w(=== == !=) | ||||||
|     MSG      = "Comparison always evaluates to %s" |  | ||||||
| 
 | 
 | ||||||
|     PRIMITIVES = { |     MSG        = "Comparison always evaluates to %s" | ||||||
|  |     MSG_LIKELY = "Comparison most likely evaluates to %s" | ||||||
|  | 
 | ||||||
|  |     PRIMITIVE_LITERAL_TYPES = { | ||||||
|       Crystal::NilLiteral, |       Crystal::NilLiteral, | ||||||
|       Crystal::BoolLiteral, |       Crystal::BoolLiteral, | ||||||
|       Crystal::NumberLiteral, |       Crystal::NumberLiteral, | ||||||
|       Crystal::CharLiteral, |       Crystal::CharLiteral, | ||||||
|       Crystal::StringLiteral, |       Crystal::StringLiteral, | ||||||
|       Crystal::SymbolLiteral, |       Crystal::SymbolLiteral, | ||||||
|  |       Crystal::ProcLiteral, | ||||||
|  |       Crystal::Path, | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     DYNAMIC_LITERAL_TYPES = { | ||||||
|       Crystal::RangeLiteral, |       Crystal::RangeLiteral, | ||||||
|       Crystal::RegexLiteral, |       Crystal::RegexLiteral, | ||||||
|       Crystal::TupleLiteral, |       Crystal::TupleLiteral, | ||||||
|       Crystal::NamedTupleLiteral, |       Crystal::NamedTupleLiteral, | ||||||
|       Crystal::ArrayLiteral, |       Crystal::ArrayLiteral, | ||||||
|       Crystal::HashLiteral, |       Crystal::HashLiteral, | ||||||
|       Crystal::ProcLiteral, |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     LITERAL_TYPES = | ||||||
|  |       PRIMITIVE_LITERAL_TYPES + DYNAMIC_LITERAL_TYPES | ||||||
|  | 
 | ||||||
|     def test(source, node : Crystal::Call) |     def test(source, node : Crystal::Call) | ||||||
|       return unless node.name.in?(OP_NAMES) |       return unless node.name.in?(OP_NAMES) | ||||||
|       return unless (obj = node.obj) && (arg = node.args.first?) |       return unless (obj = node.obj) && (arg = node.args.first?) | ||||||
|       return unless obj.class.in?(PRIMITIVES) && arg.class.in?(PRIMITIVES) | 
 | ||||||
|  |       return unless obj.class.in?(LITERAL_TYPES) && | ||||||
|  |                     arg.class.in?(LITERAL_TYPES) | ||||||
|  | 
 | ||||||
|  |       is_dynamic = obj.class.in?(DYNAMIC_LITERAL_TYPES) || | ||||||
|  |                    arg.class.in?(DYNAMIC_LITERAL_TYPES) | ||||||
| 
 | 
 | ||||||
|       what = |       what = | ||||||
|         case node.name |         case node.name | ||||||
|  | @ -52,7 +69,7 @@ module Ameba::Rule::Lint | ||||||
|         when "!="  then (obj.to_s != arg.to_s).to_s |         when "!="  then (obj.to_s != arg.to_s).to_s | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|       issue_for node, MSG % what |       issue_for node, (is_dynamic ? MSG_LIKELY : MSG) % what | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue