Skip to content

Commit 916f076

Browse files
authored
Merge pull request #243 from julia-vscode/incremental-update
add resolve only pass
2 parents b6e4034 + b5e3b39 commit 916f076

File tree

4 files changed

+78
-22
lines changed

4 files changed

+78
-22
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1515

1616
[compat]
1717
julia = "1"
18-
CSTParser = "3"
18+
CSTParser = "3.1"
1919
SymbolServer = "5.1.1"
2020

2121
[targets]

src/StaticLint.jl

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,12 @@ bindingof(m::Meta) = m.binding
6262
abstract type State end
6363
mutable struct Toplevel{T} <: State
6464
file::T
65-
targetfile::Union{Nothing,T}
6665
included_files::Vector{String}
6766
scope::Scope
67+
in_modified_expr::Bool
68+
modified_exprs::Union{Nothing,Vector{EXPR}}
6869
delayed::Vector{EXPR}
70+
resolveonly::Vector{EXPR}
6971
server
7072
end
7173

@@ -78,13 +80,22 @@ function (state::Toplevel)(x::EXPR)
7880
s0 = scopes(x, state)
7981
resolve_ref(x, state)
8082
followinclude(x, state)
81-
83+
84+
old_in_modified_expr = state.in_modified_expr
85+
if state.modified_exprs !== nothing && x in state.modified_exprs
86+
state.in_modified_expr = true
87+
end
8288
if CSTParser.defines_function(x) || CSTParser.defines_macro(x) || headof(x) === :export
83-
push!(state.delayed, x)
89+
if state.in_modified_expr
90+
push!(state.delayed, x)
91+
else
92+
push!(state.resolveonly, x)
93+
end
8494
else
8595
traverse(x, state)
8696
end
87-
97+
98+
state.in_modified_expr = old_in_modified_expr
8899
state.scope != s0 && (state.scope = s0)
89100
return state.scope
90101
end
@@ -112,6 +123,54 @@ function (state::Delayed)(x::EXPR)
112123
return state.scope
113124
end
114125

126+
mutable struct ResolveOnly <: State
127+
scope::Scope
128+
server
129+
end
130+
131+
function (state::ResolveOnly)(x::EXPR)
132+
if hasscope(x)
133+
s0 = state.scope
134+
state.scope = scopeof(x)
135+
else
136+
s0 = state.scope
137+
end
138+
resolve_ref(x, state)
139+
140+
traverse(x, state)
141+
if state.scope != s0
142+
state.scope = s0
143+
end
144+
return state.scope
145+
end
146+
147+
148+
function semantic_pass(file, modified_expr=nothing)
149+
server = file.server
150+
setscope!(getcst(file), Scope(nothing, getcst(file), Dict(), Dict{Symbol,Any}(:Base => getsymbolserver(server)[:Base], :Core => getsymbolserver(server)[:Core]), nothing))
151+
state = Toplevel(file, [getpath(file)], scopeof(getcst(file)), modified_expr === nothing, modified_expr, EXPR[], EXPR[], server)
152+
state(getcst(file))
153+
for x in state.delayed
154+
if hasscope(x)
155+
traverse(x, Delayed(scopeof(x), server))
156+
for (k, b) in scopeof(x).names
157+
infer_type_by_use(b, state.server)
158+
end
159+
else
160+
traverse(x, Delayed(retrieve_delayed_scope(x), server))
161+
end
162+
end
163+
if state.resolveonly !== nothing
164+
for x in state.resolveonly
165+
if hasscope(x)
166+
traverse(x, ResolveOnly(scopeof(x), server))
167+
else
168+
traverse(x, ResolveOnly(retrieve_delayed_scope(x), server))
169+
end
170+
end
171+
end
172+
end
173+
115174
"""
116175
traverse(x, state)
117176

src/server.jl

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,6 @@ end
3838
getsymbolserver(server::FileServer) = server.symbolserver
3939
getsymbolextendeds(server::FileServer) = server.symbol_extends
4040

41-
function semantic_pass(file, target=nothing)
42-
server = file.server
43-
setscope!(getcst(file), Scope(nothing, getcst(file), Dict(), Dict{Symbol,Any}(:Base => getsymbolserver(server)[:Base], :Core => getsymbolserver(server)[:Core]), nothing))
44-
state = Toplevel(file, target, [getpath(file)], scopeof(getcst(file)), EXPR[], server)
45-
state(getcst(file))
46-
for x in state.delayed
47-
if hasscope(x)
48-
traverse(x, Delayed(scopeof(x), server))
49-
for (k, b) in scopeof(x).names
50-
infer_type_by_use(b, state.server)
51-
end
52-
else
53-
ds = retrieve_delayed_scope(x)
54-
traverse(x, Delayed(ds, server))
55-
end
56-
end
57-
end
5841

5942
getpath(file::File) = file.path
6043

test/runtests.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,3 +1476,17 @@ end
14761476
""")
14771477
@test !StaticLint.haserror(cst.args[2])
14781478
end
1479+
1480+
@testset "reparse" begin
1481+
cst = parse_and_pass("""
1482+
x = 1
1483+
function f(arg)
1484+
x
1485+
end
1486+
""")
1487+
@test StaticLint.hasref(cst.args[2].args[2].args[1])
1488+
StaticLint.clear_meta(cst[2])
1489+
@test !StaticLint.hasref(cst.args[2].args[2].args[1])
1490+
StaticLint.semantic_pass(server.files[""], CSTParser.EXPR[cst[2]])
1491+
@test StaticLint.hasref(cst.args[2].args[2].args[1])
1492+
end

0 commit comments

Comments
 (0)