Skip to content

Commit 426cc2c

Browse files
authored
Merge pull request #337 from julia-vscode/sp/mutable-struct-const-field
Support const fields in mutable structs
2 parents 45edede + 9dc7b49 commit 426cc2c

File tree

4 files changed

+40
-26
lines changed

4 files changed

+40
-26
lines changed

src/CSTParser.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Acceptable starting tokens are:
3838
+ An `@`.
3939
4040
"""
41-
function parse_expression(ps::ParseState, esc_on_error = false)
41+
function parse_expression(ps::ParseState, esc_on_error = false; allow_const_field = false)
4242
if kindof(ps.nt) === Tokens.ENDMARKER
4343
ret = mErrorToken(ps, UnexpectedToken)
4444
elseif (esc_on_error && ps.nt.kind == Tokens.ERROR)
@@ -48,7 +48,7 @@ function parse_expression(ps::ParseState, esc_on_error = false)
4848
else
4949
next(ps)
5050
if iskeyword(kindof(ps.t)) && kindof(ps.t) != Tokens.DO
51-
ret = parse_kw(ps)
51+
ret = parse_kw(ps; allow_const_field = allow_const_field)
5252
elseif kindof(ps.t) === Tokens.LPAREN
5353
ret = parse_paren(ps)
5454
elseif kindof(ps.t) === Tokens.LSQUARE

src/components/internals.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const term_c = (Tokens.RPAREN, Tokens.RSQUARE, Tokens.RBRACE, Tokens.END, Tokens
44
Continue parsing statements until an element of `closers` is hit (usually
55
`end`). Statements are grouped in a `Block` EXPR.
66
"""
7-
function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.END,), docable=false)
7+
function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.END,), docable=false; allow_const_field = false)
88
prevpos = position(ps)
99
while kindof(ps.nt) closers # loop until an expected closer is hit
1010
if kindof(ps.nt) term_c # error handling if an unexpected closer is hit
@@ -17,7 +17,7 @@ function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.E
1717
if docable
1818
a = parse_doc(ps)
1919
else
20-
a = parse_expression(ps)
20+
a = parse_expression(ps; allow_const_field = allow_const_field)
2121
end
2222
push!(ret, a)
2323
end

src/components/keywords.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
Dispatch function for when the parser has reached a keyword.
55
"""
6-
function parse_kw(ps::ParseState)
6+
function parse_kw(ps::ParseState; allow_const_field = false)
77
k = kindof(ps.t)
88
if ps.closer.precedence == 20 && ps.lt.kind === Tokens.EX_OR && k !== Tokens.END
99
return EXPR(:IDENTIFIER, ps)
@@ -52,7 +52,7 @@ function parse_kw(ps::ParseState)
5252
elseif k === Tokens.BAREMODULE
5353
return @default ps @closer ps :block parse_blockexpr(ps, :baremodule)
5454
elseif k === Tokens.CONST
55-
return @default ps parse_const(ps)
55+
return @default ps parse_const(ps; allow_const_field = allow_const_field)
5656
elseif k === Tokens.GLOBAL
5757
return @default ps parse_local_global(ps, false)
5858
elseif k === Tokens.LOCAL
@@ -85,10 +85,10 @@ function parse_kw(ps::ParseState)
8585
end
8686
end
8787

88-
function parse_const(ps::ParseState)
88+
function parse_const(ps::ParseState; allow_const_field = false)
8989
kw = EXPR(ps)
9090
arg = parse_expression(ps)
91-
if !(isassignment(unwrapbracket(arg)) || (headof(arg) === :global && length(arg.args) > 0 && isassignment(unwrapbracket(arg.args[1]))))
91+
if !allow_const_field && !(isassignment(unwrapbracket(arg)) || (headof(arg) === :global && length(arg.args) > 0 && isassignment(unwrapbracket(arg.args[1]))))
9292
arg = mErrorToken(ps, arg, ExpectedAssignment)
9393
end
9494
ret = EXPR(:const, EXPR[arg], EXPR[kw])
@@ -154,7 +154,7 @@ function parse_mutable(ps::ParseState)
154154
if kindof(ps.nt) === Tokens.STRUCT
155155
kw = EXPR(ps)
156156
next(ps)
157-
ret = parse_blockexpr(ps, :mutable)
157+
ret = parse_blockexpr(ps, :mutable, allow_const_field = true)
158158
pushfirst!(ret.trivia, setparent!(kw, ret))
159159
update_span!(ret)
160160
else
@@ -300,15 +300,15 @@ function parse_do(ps::ParseState, pre::EXPR)
300300
end
301301

302302
"""
303-
parse_blockexpr(ps::ParseState, head)
303+
parse_blockexpr(ps::ParseState, head; allow_const_field = false)
304304
305305
General function for parsing block expressions comprised of a series of statements
306306
terminated by an `end`.
307307
"""
308-
function parse_blockexpr(ps::ParseState, head)
308+
function parse_blockexpr(ps::ParseState, head; allow_const_field = false)
309309
kw = EXPR(ps)
310310
sig = parse_blockexpr_sig(ps, head)
311-
blockargs = parse_block(ps, EXPR[], (Tokens.END,), docable(head))
311+
blockargs = parse_block(ps, EXPR[], (Tokens.END,), docable(head); allow_const_field = allow_const_field)
312312
if head === :begin
313313
EXPR(:block, blockargs, EXPR[kw, accept_end(ps)])
314314
elseif sig === nothing

test/parser.jl

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -334,25 +334,39 @@ end
334334
@test "struct a; end" |> test_expr
335335
@test "struct a; b;end" |> test_expr
336336
@test """struct a
337-
arg1
338-
end""" |> test_expr
337+
arg1
338+
end""" |> test_expr
339339
@test """struct a <: T
340-
arg1::Int
341-
arg2::Int
342-
end""" |> test_expr
340+
arg1::Int
341+
arg2::Int
342+
end""" |> test_expr
343343
@test """struct a
344-
arg1::T
345-
end""" |> test_expr
344+
arg1::T
345+
end""" |> test_expr
346346
@test """struct a{T}
347-
arg1::T
348-
a(args) = new(args)
349-
end""" |> test_expr
347+
arg1::T
348+
a(args) = new(args)
349+
end""" |> test_expr
350350
@test """struct a <: Int
351-
arg1::Vector{Int}
352-
end""" |> test_expr
351+
arg1::Vector{Int}
352+
end""" |> test_expr
353353
@test """mutable struct a <: Int
354-
arg1::Vector{Int}
355-
end""" |> test_expr
354+
arg1::Vector{Int}
355+
end""" |> test_expr
356+
if VERSION > v"1.8-"
357+
@test """mutable struct A
358+
const arg1::Vector{Int}
359+
arg2
360+
end""" |> test_expr
361+
@test """mutable struct A
362+
const arg1
363+
arg2
364+
end""" |> test_expr
365+
@test CSTParser.has_error(CSTParser.parse("""struct A
366+
const arg1
367+
arg2
368+
end"""))
369+
end
356370
end
357371
end
358372

0 commit comments

Comments
 (0)