Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Jul 19, 2025. It is now read-only.

Commit 0646b13

Browse files
Add support to scala (#324)
* Add support to scala * Filter imports by default
1 parent e48e3aa commit 0646b13

File tree

4 files changed

+309
-0
lines changed

4 files changed

+309
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 Scala
12+
class Main < CC::Engine::Analyzers::Base
13+
LANGUAGE = "scala".freeze
14+
PATTERNS = ["**/*.sc", "**/*.scala"].freeze
15+
DEFAULT_MASS_THRESHOLD = 60
16+
DEFAULT_FILTERS = [
17+
"(Import ___)".freeze,
18+
].freeze
19+
POINTS_PER_OVERAGE = 10_000
20+
REQUEST_PATH = "/scala".freeze
21+
22+
def use_sexp_lines?
23+
false
24+
end
25+
26+
private
27+
28+
def process_file(file)
29+
parse(file, REQUEST_PATH)
30+
end
31+
32+
def default_filters
33+
DEFAULT_FILTERS.map { |filter| Sexp::Matcher.parse filter }
34+
end
35+
end
36+
end
37+
end
38+
end
39+
end

‎lib/cc/engine/duplication.rb‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
require "cc/engine/analyzers/php/main"
1111
require "cc/engine/analyzers/python/main"
1212
require "cc/engine/analyzers/reporter"
13+
require "cc/engine/analyzers/scala/main"
1314
require "cc/engine/analyzers/swift/main"
1415
require "cc/engine/analyzers/typescript/main"
1516
require "cc/engine/analyzers/engine_config"
@@ -29,6 +30,7 @@ class Duplication
2930
"python" => ::CC::Engine::Analyzers::Python::Main,
3031
"typescript" => ::CC::Engine::Analyzers::TypeScript::Main,
3132
"go" => ::CC::Engine::Analyzers::Go::Main,
33+
"scala" => ::CC::Engine::Analyzers::Scala::Main,
3234
"swift" => ::CC::Engine::Analyzers::Swift::Main,
3335
}.freeze
3436

‎spec/cc/engine/analyzers/engine_config_spec.rb‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"python" => {},
5252
"typescript" => {},
5353
"go" => {},
54+
"scala" => {},
5455
"swift" => {},
5556
})
5657
end
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
require "spec_helper"
2+
require "cc/engine/analyzers/scala/main"
3+
require "cc/engine/analyzers/engine_config"
4+
5+
module CC::Engine::Analyzers
6+
RSpec.describe Scala::Main, in_tmpdir: true do
7+
include AnalyzerSpecHelpers
8+
9+
describe "#run" do
10+
let(:engine_conf) { EngineConfig.new({}) }
11+
12+
it "prints an issue for similar code" do
13+
create_source_file("foo.scala", <<-EOF)
14+
class Foo {
15+
def foo() {
16+
val anArray = new Array[Int](10)
17+
for (i <- 0 to 10) {
18+
anArray(i) = i
19+
}
20+
21+
for (i <- 0 to 10) {
22+
println(anArray(i))
23+
}
24+
25+
println("")
26+
}
27+
28+
def bar() {
29+
val anArray = new Array[Int](10)
30+
31+
for (i <- 0 to 10) {
32+
anArray(i) = i
33+
}
34+
35+
for (i <- 0 to 10) {
36+
println(anArray(i))
37+
}
38+
39+
println("")
40+
}
41+
}
42+
EOF
43+
44+
issues = run_engine(engine_conf).strip.split("0円")
45+
46+
result = issues.first.strip
47+
json = JSON.parse(result)
48+
49+
expect(json["type"]).to eq("issue")
50+
expect(json["check_name"]).to eq("similar-code")
51+
expect(json["description"]).to eq("Similar blocks of code found in 2 locations. Consider refactoring.")
52+
expect(json["categories"]).to eq(["Duplication"])
53+
expect(json["location"]).to eq({
54+
"path" => "foo.scala",
55+
"lines" => { "begin" => 2, "end" => 13 },
56+
})
57+
expect(json["other_locations"]).to eq([
58+
{"path" => "foo.scala", "lines" => { "begin" => 15, "end" => 27 } },
59+
])
60+
expect(json["severity"]).to eq(CC::Engine::Analyzers::Base::MAJOR)
61+
end
62+
63+
it "prints an issue for identical code" do
64+
create_source_file("foo.scala", <<-EOF)
65+
class Foo {
66+
def foo() {
67+
val anArray = new Array[Int](10)
68+
for (i <- 0 to 10) {
69+
anArray(i) = i
70+
}
71+
72+
for (i <- 0 to 10) {
73+
println(anArray(i))
74+
}
75+
76+
println("")
77+
}
78+
79+
def foo() {
80+
val anArray = new Array[Int](10)
81+
for (i <- 0 to 10) {
82+
anArray(i) = i
83+
}
84+
85+
for (i <- 0 to 10) {
86+
println(anArray(i))
87+
}
88+
89+
println("")
90+
}
91+
}
92+
EOF
93+
94+
issues = run_engine(engine_conf).strip.split("0円")
95+
result = issues.first.strip
96+
json = JSON.parse(result)
97+
98+
expect(json["type"]).to eq("issue")
99+
expect(json["check_name"]).to eq("identical-code")
100+
expect(json["description"]).to eq("Identical blocks of code found in 2 locations. Consider refactoring.")
101+
expect(json["categories"]).to eq(["Duplication"])
102+
expect(json["location"]).to eq({
103+
"path" => "foo.scala",
104+
"lines" => { "begin" => 2, "end" => 13 },
105+
})
106+
expect(json["other_locations"]).to eq([
107+
{"path" => "foo.scala", "lines" => { "begin" => 15, "end" => 26 } },
108+
])
109+
expect(json["severity"]).to eq(CC::Engine::Analyzers::Base::MAJOR)
110+
end
111+
112+
it "outputs a warning for unprocessable errors" do
113+
create_source_file("foo.scala", <<-EOF)
114+
---
115+
EOF
116+
117+
expect(CC.logger).to receive(:warn).with(/Response status: 422/)
118+
expect(CC.logger).to receive(:warn).with(/Skipping/)
119+
run_engine(engine_conf)
120+
end
121+
122+
it "ignores import and package declarations" do
123+
create_source_file("foo.scala", <<-EOF)
124+
package org.springframework.rules.constraint;
125+
126+
import java.util.Comparator;
127+
128+
import org.springframework.rules.constraint.Constraint;
129+
import org.springframework.rules.closure.BinaryConstraint;
130+
EOF
131+
132+
create_source_file("bar.scala", <<-EOF)
133+
package org.springframework.rules.constraint;
134+
135+
import java.util.Comparator;
136+
137+
import org.springframework.rules.constraint.Constraint;
138+
import org.springframework.rules.closure.BinaryConstraint;
139+
EOF
140+
141+
conf = CC::Engine::Analyzers::EngineConfig.new({
142+
'config' => {
143+
'checks' => {
144+
'similar-code' => { 'enabled' => true },
145+
'identical-code' => { 'enabled' => true },
146+
},
147+
'languages' => {
148+
'scala' => { 'mass_threshold' => 9 },
149+
},
150+
},
151+
})
152+
153+
issues = run_engine(conf).strip.split("0円")
154+
expect(issues).to be_empty
155+
end
156+
157+
it "prints an issue for similar code when the only difference is the value of a literal" do
158+
create_source_file("foo.sc", <<-EOF)
159+
class ArrayDemo {
160+
def foo() {
161+
val scott = arrayOfInt(
162+
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F
163+
)
164+
165+
val anArray: Array[Int] = Array(10)
166+
167+
for (i <- 0 to 10) {
168+
anArray(i) = i
169+
}
170+
171+
for (i <- 0 to 10) {
172+
println(anArray(i) + " ")
173+
}
174+
175+
println()
176+
}
177+
178+
def foo() {
179+
val scott = arrayOfInt(
180+
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7
181+
)
182+
183+
val anArray: Array[Int] = Array(10)
184+
185+
for (i <- 0 to 10) {
186+
anArray(i) = i
187+
}
188+
189+
for (i <- 0 to 10) {
190+
println(anArray(i) + " ")
191+
}
192+
193+
println()
194+
}
195+
}
196+
EOF
197+
198+
issues = run_engine(engine_conf).strip.split("0円")
199+
expect(issues.length).to be > 0
200+
result = issues.first.strip
201+
json = JSON.parse(result)
202+
203+
expect(json["type"]).to eq("issue")
204+
expect(json["check_name"]).to eq("similar-code")
205+
206+
expect(json["description"]).to eq("Similar blocks of code found in 2 locations. Consider refactoring.")
207+
expect(json["categories"]).to eq(["Duplication"])
208+
expect(json["location"]).to eq({
209+
"path" => "foo.sc",
210+
"lines" => { "begin" => 2, "end" => 18 },
211+
})
212+
expect(json["other_locations"]).to eq([
213+
{"path" => "foo.sc", "lines" => { "begin" => 20, "end" => 36 } },
214+
])
215+
expect(json["severity"]).to eq(CC::Engine::Analyzers::Base::MAJOR)
216+
end
217+
218+
it "ignores comment docs and comments" do
219+
create_source_file("foo.sc", <<-EOF)
220+
/********************************************************************
221+
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com>
222+
*******************************************************************/
223+
224+
package com.github.shadowsocks.acl
225+
// Comment here
226+
227+
import org.junit.Assert
228+
import org.junit.Test
229+
230+
class AclTest {
231+
// Comment here
232+
companion object {
233+
private const val INPUT1 = """[proxy_all]
234+
[bypass_list]
235+
1.0.1.0/24
236+
(^|\.)4tern\.com${'$'}
237+
"""
238+
}
239+
240+
def parse() {
241+
Assert.assertEquals(INPUT1, Acl().fromReader(INPUT1.reader()).toString());
242+
}
243+
}
244+
EOF
245+
246+
create_source_file("bar.sc", <<-EOF)
247+
/*********************************************************************
248+
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com>
249+
********************************************************************/
250+
251+
package com.evernote.android.job
252+
// Comment here
253+
254+
object JobConstants {
255+
// Comment here
256+
const val DATABASE_NAME = JobStorage.DATABASE_NAME
257+
const val PREF_FILE_NAME = JobStorage.PREF_FILE_NAME
258+
}
259+
EOF
260+
261+
issues = run_engine(engine_conf).strip.split("0円")
262+
expect(issues).to be_empty
263+
end
264+
265+
end
266+
end
267+
end

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /