Skip to content

Commit c4a3032

Browse files
committed
Merge branch 'master' into sp/large-file-limit
2 parents ec6ed82 + 5fb681c commit c4a3032

File tree

4 files changed

+145
-60
lines changed

4 files changed

+145
-60
lines changed

src/StaticLint.jl

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ include("scope.jl")
1717
include("subtypes.jl")
1818
include("methodmatching.jl")
1919

20-
const LARGE_FILE_LIMIT = 1_000_000 # bytes
20+
const LARGE_FILE_LIMIT = 2_000_000 # bytes
2121

2222
mutable struct Meta
2323
binding::Union{Nothing,Binding}
@@ -229,6 +229,20 @@ function traverse(x::EXPR, state)
229229
end
230230
end
231231

232+
function check_filesize(x, path)
233+
nb = try
234+
filesize(path)
235+
catch
236+
seterror!(x, FileNotAvailable)
237+
return false
238+
end
239+
240+
toobig = nb > LARGE_FILE_LIMIT
241+
if toobig
242+
seterror!(x, FileTooBig)
243+
end
244+
return !toobig
245+
end
232246

233247
"""
234248
followinclude(x, state)
@@ -247,7 +261,11 @@ function followinclude(x, state::State)
247261
elseif isabspath(path)
248262
if hasfile(state.server, path)
249263
elseif canloadfile(state.server, path)
250-
loadfile(state.server, path)
264+
if check_filesize(x, path)
265+
loadfile(state.server, path)
266+
else
267+
return
268+
end
251269
else
252270
path = ""
253271
end
@@ -257,7 +275,11 @@ function followinclude(x, state::State)
257275
path = joinpath(dirname(getpath(state.file)), path)
258276
elseif canloadfile(state.server, joinpath(dirname(getpath(state.file)), path))
259277
path = joinpath(dirname(getpath(state.file)), path)
260-
loadfile(state.server, path)
278+
if check_filesize(x, path)
279+
loadfile(state.server, path)
280+
else
281+
return
282+
end
261283
else
262284
path = ""
263285
end
@@ -280,6 +302,7 @@ function followinclude(x, state::State)
280302
return
281303
end
282304
f = getfile(state.server, path)
305+
283306
if f.cst.fullspan > LARGE_FILE_LIMIT
284307
seterror!(x, FileTooBig)
285308
return

src/linting/checks.jl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
DuplicateFuncArgName,
3232
IncludePathContainsNULL,
3333
IndexFromLength,
34-
FileTooBig
34+
FileTooBig,
35+
FileNotAvailable,
3536
)
3637

3738
const LintCodeDescriptions = Dict{LintCodes,String}(
@@ -65,6 +66,7 @@ const LintCodeDescriptions = Dict{LintCodes,String}(
6566
IncludePathContainsNULL => "Cannot include file, path contains NULL characters.",
6667
IndexFromLength => "Indexing with indices obtained from `length`, `size` etc is discouraged. Use `eachindex` or `axes` instead.",
6768
FileTooBig => "File too big, not following include.",
69+
FileNotAvailable => "File not available."
6870
)
6971

7072
haserror(m::Meta) = m.error !== nothing
@@ -554,12 +556,15 @@ function check_farg_unused(x::EXPR)
554556
end
555557

556558
function check_farg_unused_(arg, arg_names)
557-
if hasbinding(arg)
558-
elseif iskwarg(arg) && hasbinding(arg.args[1])
559-
arg = arg.args[1]
560-
elseif is_nospecialize_call(arg) && hasbinding(unwrap_nospecialize(arg))
561-
arg = unwrap_nospecialize(arg)
562-
else
559+
if !hasbinding(arg)
560+
if iskwarg(arg)
561+
arg = arg.args[1]
562+
end
563+
if is_nospecialize_call(arg)
564+
arg = unwrap_nospecialize(arg)
565+
end
566+
end
567+
if !hasbinding(arg)
563568
return false
564569
end
565570
b = bindingof(arg)

src/type_inf.jl

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ function infer_type(binding::Binding, scope, state)
3333
end
3434

3535
function infer_type_assignment_rhs(binding, state, scope)
36+
is_destructuring = false
37+
lhs = binding.val.args[1]
3638
rhs = binding.val.args[2]
3739
if is_loop_iter_assignment(binding.val)
3840
settype!(binding, infer_eltype(rhs))
@@ -43,13 +45,24 @@ function infer_type_assignment_rhs(binding, state, scope)
4345
end
4446
else
4547
if CSTParser.is_func_call(rhs)
48+
if CSTParser.istuple(lhs)
49+
if CSTParser.isparameters(lhs.args[1])
50+
is_destructuring = true
51+
else
52+
return
53+
end
54+
end
4655
callname = CSTParser.get_name(rhs)
4756
if isidentifier(callname)
4857
resolve_ref(callname, scope, state)
4958
if hasref(callname)
5059
rb = get_root_method(refof(callname), state.server)
5160
if (rb isa Binding && (CoreTypes.isdatatype(rb.type) || rb.val isa SymbolServer.DataTypeStore)) || rb isa SymbolServer.DataTypeStore
52-
settype!(binding, rb)
61+
if is_destructuring
62+
infer_destructuring_type(binding, rb)
63+
else
64+
settype!(binding, rb)
65+
end
5366
end
5467
end
5568
end
@@ -94,6 +107,26 @@ function infer_type_assignment_rhs(binding, state, scope)
94107
end
95108
end
96109

110+
function infer_destructuring_type(binding, rb::SymbolServer.DataTypeStore)
111+
assigned_name = CSTParser.get_name(binding.val)
112+
for (fieldname, fieldtype) in zip(rb.val.fieldnames, rb.val.types)
113+
if fieldname == assigned_name
114+
settype!(binding, fieldtype)
115+
return
116+
end
117+
end
118+
end
119+
function infer_destructuring_type(binding::Binding, rb::EXPR)
120+
assigned_name = string(to_codeobject(binding.name))
121+
scope = scopeof(rb)
122+
names = scope.names
123+
if haskey(names, assigned_name)
124+
b = names[assigned_name]
125+
settype!(binding, b.type)
126+
end
127+
end
128+
infer_destructuring_type(binding, rb::Binding) = infer_destructuring_type(binding, rb.val)
129+
97130
function infer_type_decl(binding, state, scope)
98131
t = binding.val.args[2]
99132
if isidentifier(t)

test/runtests.jl

Lines changed: 73 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,11 @@ f(arg) = arg
187187
@test StaticLint.CoreTypes.ismodule(bindingof(parse_and_pass("module A end").args[1]).type)
188188
@test StaticLint.CoreTypes.ismodule(bindingof(parse_and_pass("baremodule A end").args[1]).type)
189189

190-
# @test parse_and_pass("function f(x::Int) x end")[1][2][3].binding.t == StaticLint.getsymbolserver(server)["Core"].vals["Function"]
190+
# @test parse_and_pass("function f(x::Int) x end")[1][2][3].binding.t == StaticLint.getsymbolserver(server)["Core"].vals["Function"]
191191
let cst = parse_and_pass("""
192192
struct T end
193-
function f(x::T) x end""")
193+
function f(x::T) x end
194+
""")
194195
@test StaticLint.CoreTypes.isdatatype(bindingof(cst.args[1]).type)
195196
@test StaticLint.CoreTypes.isfunction(bindingof(cst.args[2]).type)
196197
@test bindingof(cst.args[2].args[1].args[2]).type == bindingof(cst.args[1])
@@ -199,7 +200,8 @@ f(arg) = arg
199200
let cst = parse_and_pass("""
200201
struct T end
201202
T() = 1
202-
function f(x::T) x end""")
203+
function f(x::T) x end
204+
""")
203205
@test StaticLint.CoreTypes.isdatatype(bindingof(cst.args[1]).type)
204206
@test StaticLint.CoreTypes.isfunction(bindingof(cst.args[3]).type)
205207
@test bindingof(cst.args[3].args[1].args[2]).type == bindingof(cst.args[1])
@@ -208,7 +210,8 @@ f(arg) = arg
208210

209211
let cst = parse_and_pass("""
210212
struct T end
211-
t = T()""")
213+
t = T()
214+
""")
212215
@test StaticLint.CoreTypes.isdatatype(bindingof(cst.args[1]).type)
213216
@test bindingof(cst.args[2].args[1]).type == bindingof(cst.args[1])
214217
end
@@ -222,7 +225,8 @@ f(arg) = arg
222225
import ..B
223226
B.x
224227
end
225-
end""")
228+
end
229+
""")
226230
@test refof(cst.args[1].args[3].args[2].args[3].args[2].args[2].args[1]) == bindingof(cst[1].args[3].args[1].args[3].args[1].args[1])
227231
end
228232

@@ -235,7 +239,8 @@ f(arg) = arg
235239
end
236240
function f(arg::T1)
237241
arg.field.x
238-
end""");
242+
end
243+
""");
239244
@test refof(cst.args[3].args[2].args[1].args[1].args[1]) == bindingof(cst.args[3].args[1].args[2])
240245
@test refof(cst.args[3].args[2].args[1].args[1].args[2].args[1]) == bindingof(cst.args[2].args[3].args[1])
241246
@test refof(cst.args[3].args[2].args[1].args[2].args[1]) == bindingof(cst.args[1].args[3].args[1])
@@ -246,9 +251,9 @@ f(arg) = arg
246251
end
247252

248253
let cst = parse_and_pass("""
249-
macro mac_str() end
250-
mac"whatever"
251-
""")
254+
macro mac_str() end
255+
mac"whatever"
256+
""")
252257
@test refof(cst.args[2].args[1]) == bindingof(cst.args[1])
253258
end
254259

@@ -261,50 +266,50 @@ f(arg) = arg
261266
end
262267

263268
let cst = parse_and_pass("""
264-
module Reparse
265-
end
266-
using .Reparse, CSTParser
267-
""")
269+
module Reparse
270+
end
271+
using .Reparse, CSTParser
272+
""")
268273
@test refof(cst.args[2].args[1].args[2]).val == bindingof(cst[1])
269274
end
270275

271276
let cst = parse_and_pass("""
272-
module A
273-
A
274-
end
275-
""")
277+
module A
278+
A
279+
end
280+
""")
276281
@test scopeof(cst).names["A"] == scopeof(cst.args[1]).names["A"]
277282
@test refof(cst.args[1].args[2]) == bindingof(cst.args[1])
278283
@test refof(cst.args[1].args[3].args[1]) == bindingof(cst.args[1])
279284
end
280-
# let cst = parse_and_pass("""
281-
# using Test: @test
282-
# """)
283-
# @test bindingof(cst[1][4]) !== nothing
284-
# end
285+
# let cst = parse_and_pass("""
286+
# using Test: @test
287+
# """)
288+
# @test bindingof(cst[1][4]) !== nothing
289+
# end
285290
let cst = parse_and_pass("""
286-
sin(1,2,3)
287-
""")
291+
sin(1,2,3)
292+
""")
288293
@test errorof(cst.args[1]) === StaticLint.IncorrectCallArgs
289294
end
290295
let cst = parse_and_pass("""
291-
for i in length(1) end
292-
for i in 1.1 end
293-
for i in 1 end
294-
for i in 1:1 end
295-
""")
296+
for i in length(1) end
297+
for i in 1.1 end
298+
for i in 1 end
299+
for i in 1:1 end
300+
""")
296301
@test errorof(cst.args[1].args[1]) === StaticLint.IncorrectIterSpec
297302
@test errorof(cst.args[2].args[1]) === StaticLint.IncorrectIterSpec
298303
@test errorof(cst.args[3].args[1]) === StaticLint.IncorrectIterSpec
299304
@test errorof(cst.args[4].args[1]) === nothing
300305
end
301306

302307
let cst = parse_and_pass("""
303-
[i for i in length(1) end]
304-
[i for i in 1.1 end]
305-
[i for i in 1 end]
306-
[i for i in 1:1 end]
307-
""")
308+
[i for i in length(1) end]
309+
[i for i in 1.1 end]
310+
[i for i in 1 end]
311+
[i for i in 1:1 end]
312+
""")
308313
@test errorof(cst[1][2][3]) === StaticLint.IncorrectIterSpec
309314
@test errorof(cst[2][2][3]) === StaticLint.IncorrectIterSpec
310315
@test errorof(cst[3][2][3]) === StaticLint.IncorrectIterSpec
@@ -319,29 +324,44 @@ f(arg) = arg
319324
end
320325

321326
let cst = parse_and_pass("""
322-
struct Graph
323-
children:: T
324-
end
327+
struct Graph
328+
children:: T
329+
end
325330
326-
function test()
327-
g = Graph()
328-
f = g.children
329-
end""")
331+
function test()
332+
g = Graph()
333+
f = g.children
334+
end""")
330335
@test cst.args[2].args[2].args[2].args[2].args[2].args[1] in bindingof(cst.args[1].args[3].args[1]).refs
331336
end
332337

333338
let cst = parse_and_pass("""
334-
__source__
335-
__module__
336-
macro m()
337-
__source__
338-
__module__
339-
end""")
339+
__source__
340+
__module__
341+
macro m()
342+
__source__
343+
__module__
344+
end""")
340345
@test refof(cst[1]) === nothing
341346
@test refof(cst[2]) === nothing
342347
@test refof(cst[3][3][1]) !== nothing
343348
@test refof(cst[3][3][2]) !== nothing
344349
end
350+
351+
let cst = parse_and_pass("""
352+
struct Foo
353+
x::DataType
354+
y::Float64
355+
end
356+
(;x, y) = Foo(1,2)
357+
x
358+
y
359+
""")
360+
mx = cst.args[3].meta
361+
@test mx.ref.type.name.name.name == :DataType
362+
my = cst.args[4].meta
363+
@test my.ref.type.name.name.name == :Float64
364+
end
345365
end
346366

347367
@testset "macros" begin
@@ -1351,9 +1371,13 @@ f(arg) = arg
13511371
@testset "issue 1609" begin
13521372
let
13531373
cst1 = parse_and_pass("function g(@nospecialize(x), y) x + y end")
1354-
cst2 = parse_and_pass("function g(@nospecialize(x), y) y end")
1374+
cst2 = parse_and_pass("function g(@nospecialize(x) = 1) x end")
1375+
cst3 = parse_and_pass("function g(@nospecialize(x) = 1, y = 2) x + y end")
1376+
cst4 = parse_and_pass("function g(@nospecialize(x), y) y end")
13551377
@test !StaticLint.haserror(cst1.args[1].args[1].args[2].args[3])
1356-
@test StaticLint.haserror(cst2.args[1].args[1].args[2].args[3])
1378+
@test !StaticLint.haserror(cst2.args[1].args[1].args[2].args[1])
1379+
@test !StaticLint.haserror(cst3.args[1].args[1].args[2].args[1])
1380+
@test StaticLint.haserror(cst4.args[1].args[1].args[2].args[3])
13571381
end
13581382
end
13591383

0 commit comments

Comments
 (0)