Skip to content

Commit 79dc669

Browse files
committed
[wip] Added kotlin duplication checks
1 parent e166105 commit 79dc669

File tree

4 files changed

+261
-0
lines changed

4 files changed

+261
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# frozen_string_literal: true
2+
3+
require "flay"
4+
require "json"
5+
require "cc/engine/analyzers/reporter"
6+
require "cc/engine/analyzers/analyzer_base"
7+
8+
module CC
9+
module Engine
10+
module Analyzers
11+
module Kotlin
12+
class Main < CC::Engine::Analyzers::Base
13+
LANGUAGE = "kotlin".freeze
14+
PATTERNS = ["**/*.kt"].freeze
15+
DEFAULT_MASS_THRESHOLD = 40
16+
DEFAULT_FILTERS = [
17+
"(IMPORT_LIST ___)".freeze,
18+
"(PACKAGE_DIRECTIVE ___)".freeze,
19+
].freeze
20+
POINTS_PER_OVERAGE = 10_000
21+
REQUEST_PATH = "/kotlin".freeze
22+
23+
def use_sexp_lines?
24+
false
25+
end
26+
27+
private
28+
29+
def process_file(file)
30+
parse(file, REQUEST_PATH)
31+
end
32+
33+
def default_filters
34+
DEFAULT_FILTERS.map { |filter| Sexp::Matcher.parse filter }
35+
end
36+
end
37+
end
38+
end
39+
end
40+
end

lib/cc/engine/duplication.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
require "cc/engine/parse_metrics"
55
require "cc/engine/analyzers/ruby/main"
66
require "cc/engine/analyzers/java/main"
7+
require "cc/engine/analyzers/kotlin/main"
78
require "cc/engine/analyzers/javascript/main"
89
require "cc/engine/analyzers/go/main"
910
require "cc/engine/analyzers/php/main"
@@ -22,6 +23,7 @@ class Duplication
2223
LANGUAGES = {
2324
"ruby" => ::CC::Engine::Analyzers::Ruby::Main,
2425
"java" => ::CC::Engine::Analyzers::Java::Main,
26+
"kotlin" => ::CC::Engine::Analyzers::Kotlin::Main,
2527
"javascript" => ::CC::Engine::Analyzers::Javascript::Main,
2628
"php" => ::CC::Engine::Analyzers::Php::Main,
2729
"python" => ::CC::Engine::Analyzers::Python::Main,

spec/cc/engine/analyzers/engine_config_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
expect(engine_config.languages).to eq({
4646
"ruby" => {},
4747
"java" => {},
48+
"kotlin" => {},
4849
"javascript" => {},
4950
"php" => {},
5051
"python" => {},
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
=begin
2+
require "spec_helper"
3+
require "cc/engine/analyzers/java/main"
4+
require "cc/engine/analyzers/engine_config"
5+
6+
module CC::Engine::Analyzers
7+
RSpec.describe Java::Main, in_tmpdir: true do
8+
include AnalyzerSpecHelpers
9+
10+
describe "#run" do
11+
let(:engine_conf) { EngineConfig.new({}) }
12+
13+
it "prints an issue for similar code" do
14+
create_source_file("foo.java", <<-EOF)
15+
public class ArrayDemo {
16+
public static void foo() {
17+
int[] anArray;
18+
19+
anArray = new int[10];
20+
21+
for (int i = 0; i < anArray.length; i++) {
22+
anArray[i] = i;
23+
}
24+
25+
for (int i = 0; i < anArray.length; i++) {
26+
System.out.print(anArray[i] + " ");
27+
}
28+
29+
System.out.println();
30+
}
31+
32+
public static void bar() {
33+
int[] anArray;
34+
35+
anArray = new int[10];
36+
37+
for (int i = 0; i < anArray.length; i++) {
38+
anArray[i] = i;
39+
}
40+
41+
for (int i = 0; i < anArray.length; i++) {
42+
System.out.print(anArray[i] + " ");
43+
}
44+
45+
System.out.println();
46+
}
47+
}
48+
EOF
49+
50+
issues = run_engine(engine_conf).strip.split("\0")
51+
result = issues.first.strip
52+
json = JSON.parse(result)
53+
54+
expect(json["type"]).to eq("issue")
55+
expect(json["check_name"]).to eq("similar-code")
56+
expect(json["description"]).to eq("Similar blocks of code found in 2 locations. Consider refactoring.")
57+
expect(json["categories"]).to eq(["Duplication"])
58+
expect(json["location"]).to eq({
59+
"path" => "foo.java",
60+
"lines" => { "begin" => 2, "end" => 16 },
61+
})
62+
expect(json["remediation_points"]).to eq(930_000)
63+
expect(json["other_locations"]).to eq([
64+
{"path" => "foo.java", "lines" => { "begin" => 18, "end" => 32 } },
65+
])
66+
expect(json["content"]["body"]).to match /This issue has a mass of 103/
67+
expect(json["fingerprint"]).to eq("48eb151dc29634f90a86ffabf9d3c4b5")
68+
expect(json["severity"]).to eq(CC::Engine::Analyzers::Base::MAJOR)
69+
end
70+
71+
it "prints an issue for identical code" do
72+
create_source_file("foo.java", <<-EOF)
73+
public class ArrayDemo {
74+
public static void foo(int[] anArray) {
75+
for (int i = 0; i < anArray.length; i++) {
76+
System.out.print(anArray[i] + " ");
77+
}
78+
79+
System.out.println();
80+
}
81+
82+
public static void foo(int[] anArray) {
83+
for (int i = 0; i < anArray.length; i++) {
84+
System.out.print(anArray[i] + " ");
85+
}
86+
87+
System.out.println();
88+
}
89+
}
90+
EOF
91+
92+
issues = run_engine(engine_conf).strip.split("\0")
93+
result = issues.first.strip
94+
json = JSON.parse(result)
95+
96+
expect(json["type"]).to eq("issue")
97+
expect(json["check_name"]).to eq("identical-code")
98+
expect(json["description"]).to eq("Identical blocks of code found in 2 locations. Consider refactoring.")
99+
expect(json["categories"]).to eq(["Duplication"])
100+
expect(json["location"]).to eq({
101+
"path" => "foo.java",
102+
"lines" => { "begin" => 2, "end" => 8 },
103+
})
104+
expect(json["remediation_points"]).to eq(420_000)
105+
expect(json["other_locations"]).to eq([
106+
{"path" => "foo.java", "lines" => { "begin" => 10, "end" => 16 } },
107+
])
108+
expect(json["content"]["body"]).to match /This issue has a mass of 52/
109+
expect(json["fingerprint"]).to eq("dbb957b34f7b5312538235c0aa3f52a0")
110+
expect(json["severity"]).to eq(CC::Engine::Analyzers::Base::MINOR)
111+
end
112+
113+
it "outputs a warning for unprocessable errors" do
114+
create_source_file("foo.java", <<-EOF)
115+
---
116+
EOF
117+
118+
expect(CC.logger).to receive(:warn).with(/Response status: 422/)
119+
expect(CC.logger).to receive(:warn).with(/Skipping/)
120+
run_engine(engine_conf)
121+
end
122+
123+
it "ignores import and package declarations" do
124+
create_source_file("foo.java", <<-EOF)
125+
package org.springframework.rules.constraint;
126+
127+
import java.util.Comparator;
128+
129+
import org.springframework.rules.constraint.Constraint;
130+
import org.springframework.rules.closure.BinaryConstraint;
131+
EOF
132+
133+
create_source_file("bar.java", <<-EOF)
134+
package org.springframework.rules.constraint;
135+
136+
import java.util.Comparator;
137+
138+
import org.springframework.rules.constraint.Constraint;
139+
import org.springframework.rules.closure.BinaryConstraint;
140+
EOF
141+
142+
issues = run_engine(engine_conf).strip.split("\0")
143+
expect(issues).to be_empty
144+
end
145+
146+
it "prints an issue for similar code when the only difference is the value of a literal" do
147+
create_source_file("foo.java", <<-EOF)
148+
public class ArrayDemo {
149+
public static void foo() {
150+
int[] scott;
151+
scott = new int[] {
152+
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F
153+
};
154+
155+
int[] anArray;
156+
157+
anArray = new int[10];
158+
159+
for (int i = 0; i < anArray.length; i++) {
160+
anArray[i] = i;
161+
}
162+
163+
for (int i = 0; i < anArray.length; i++) {
164+
System.out.print(anArray[i] + " ");
165+
}
166+
167+
System.out.println();
168+
}
169+
170+
public static void foo() {
171+
int[] scott;
172+
scott = new int[] {
173+
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7
174+
};
175+
176+
int[] anArray;
177+
178+
anArray = new int[10];
179+
180+
for (int i = 0; i < anArray.length; i++) {
181+
anArray[i] = i;
182+
}
183+
184+
for (int i = 0; i < anArray.length; i++) {
185+
System.out.print(anArray[i] + " ");
186+
}
187+
188+
System.out.println();
189+
}
190+
}
191+
EOF
192+
193+
issues = run_engine(engine_conf).strip.split("\0")
194+
expect(issues.length).to be > 0
195+
result = issues.first.strip
196+
json = JSON.parse(result)
197+
198+
expect(json["type"]).to eq("issue")
199+
expect(json["check_name"]).to eq("similar-code")
200+
201+
expect(json["description"]).to eq("Similar blocks of code found in 2 locations. Consider refactoring.")
202+
expect(json["categories"]).to eq(["Duplication"])
203+
expect(json["location"]).to eq({
204+
"path" => "foo.java",
205+
"lines" => { "begin" => 2, "end" => 21 },
206+
})
207+
expect(json["remediation_points"]).to eq(1_230_000)
208+
expect(json["other_locations"]).to eq([
209+
{"path" => "foo.java", "lines" => { "begin" => 23, "end" => 42 } },
210+
])
211+
expect(json["content"]["body"]).to match /This issue has a mass of 133/
212+
expect(json["fingerprint"]).to eq("9abf88bac3a56bf708a5c4ceaf251d98")
213+
expect(json["severity"]).to eq(CC::Engine::Analyzers::Base::MAJOR)
214+
end
215+
end
216+
end
217+
end
218+
=end

0 commit comments

Comments
 (0)