mirror of
				https://gitea.invidious.io/iv-org/shard-ameba.git
				synced 2024-08-15 00:53:29 +00:00 
			
		
		
		
	Merge pull request #292 from crystal-ameba/Sija/lint-static-comparison
This commit is contained in:
		
						commit
						23ca87ff0e
					
				
					 2 changed files with 117 additions and 0 deletions
				
			
		
							
								
								
									
										59
									
								
								spec/ameba/rule/lint/static_comparison_spec.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								spec/ameba/rule/lint/static_comparison_spec.cr
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| require "../../../spec_helper" | ||||
| 
 | ||||
| module Ameba::Rule::Lint | ||||
|   subject = StaticComparison.new | ||||
| 
 | ||||
|   describe StaticComparison do | ||||
|     it "passes for valid cases" do | ||||
|       expect_no_issues subject, <<-CRYSTAL | ||||
|         "foo" == foo | ||||
|         "foo" != foo | ||||
|         foo == "foo" | ||||
|         foo != "foo" | ||||
|         CRYSTAL | ||||
|     end | ||||
| 
 | ||||
|     it "reports if there is a static comparison evaluating to the same" do | ||||
|       expect_issue subject, <<-CRYSTAL | ||||
|         "foo" === "foo" | ||||
|         # ^^^^^^^^^^^^^ error: Comparison always evaluates to the same | ||||
|         CRYSTAL | ||||
|     end | ||||
| 
 | ||||
|     it "reports if there is a static comparison evaluating to true (2)" do | ||||
|       expect_issue subject, <<-CRYSTAL | ||||
|         "foo" == "foo" | ||||
|         # ^^^^^^^^^^^^ error: Comparison always evaluates to true | ||||
|         CRYSTAL | ||||
|     end | ||||
| 
 | ||||
|     it "reports if there is a static comparison evaluating to false" do | ||||
|       expect_issue subject, <<-CRYSTAL | ||||
|         "foo" != "foo" | ||||
|         # ^^^^^^^^^^^^ error: Comparison always evaluates to false | ||||
|         CRYSTAL | ||||
|     end | ||||
| 
 | ||||
|     context "macro" do | ||||
|       it "reports in macro scope" do | ||||
|         expect_issue subject, <<-CRYSTAL | ||||
|           {{ "foo" == "foo" }} | ||||
|            # ^^^^^^^^^^^^^^ error: Comparison always evaluates to true | ||||
|           CRYSTAL | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     it "reports rule, pos and message" do | ||||
|       s = Source.new %( | ||||
|         "foo" == "foo" | ||||
|       ), "source.cr" | ||||
|       subject.catch(s).should_not be_valid | ||||
|       issue = s.issues.first | ||||
| 
 | ||||
|       issue.rule.should_not be_nil | ||||
|       issue.location.to_s.should eq "source.cr:1:1" | ||||
|       issue.end_location.to_s.should eq "source.cr:1:14" | ||||
|       issue.message.should eq "Comparison always evaluates to true" | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										58
									
								
								src/ameba/rule/lint/static_comparison.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/ameba/rule/lint/static_comparison.cr
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| module Ameba::Rule::Lint | ||||
|   # This rule is used to identify static comparisons - | ||||
|   # the ones that will always have the same result. | ||||
|   # | ||||
|   # For example, this will be always false: | ||||
|   # | ||||
|   # ``` | ||||
|   # "foo" == 42 | ||||
|   # ``` | ||||
|   # | ||||
|   # YAML configuration example: | ||||
|   # | ||||
|   # ``` | ||||
|   # Lint/StaticComparison: | ||||
|   #   Enabled: true | ||||
|   # ``` | ||||
|   class StaticComparison < Base | ||||
|     include AST::Util | ||||
| 
 | ||||
|     properties do | ||||
|       description "Identifies static comparisons" | ||||
|     end | ||||
| 
 | ||||
|     OP_NAMES = %w(=== == !=) | ||||
|     MSG      = "Comparison always evaluates to %s" | ||||
| 
 | ||||
|     PRIMITIVES = { | ||||
|       Crystal::NilLiteral, | ||||
|       Crystal::BoolLiteral, | ||||
|       Crystal::NumberLiteral, | ||||
|       Crystal::CharLiteral, | ||||
|       Crystal::StringLiteral, | ||||
|       Crystal::SymbolLiteral, | ||||
|       Crystal::RangeLiteral, | ||||
|       Crystal::RegexLiteral, | ||||
|       Crystal::TupleLiteral, | ||||
|       Crystal::NamedTupleLiteral, | ||||
|       Crystal::ArrayLiteral, | ||||
|       Crystal::HashLiteral, | ||||
|       Crystal::ProcLiteral, | ||||
|     } | ||||
| 
 | ||||
|     def test(source, node : Crystal::Call) | ||||
|       return unless node.name.in?(OP_NAMES) | ||||
|       return unless (obj = node.obj) && (arg = node.args.first?) | ||||
|       return unless obj.class.in?(PRIMITIVES) && arg.class.in?(PRIMITIVES) | ||||
| 
 | ||||
|       what = | ||||
|         case node.name | ||||
|         when "===" then "the same" | ||||
|         when "=="  then (obj.to_s == arg.to_s).to_s | ||||
|         when "!="  then (obj.to_s != arg.to_s).to_s | ||||
|         end | ||||
| 
 | ||||
|       issue_for node, MSG % what | ||||
|     end | ||||
|   end | ||||
| end | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue