Skip to content

Commit 110e9ba

Browse files
LiozouKristofferC
authored andcommitted
Handle infix operators in REPL completion (#51366)
Fix #51194 This PR fixes a regression introduced in #49294, so I believe it should be backported to v1.10. In the current code, completion of `qux(foo, bar.` is detected by parsing `foo(qux, bar` as an incomplete expression, and then looking for the sub-expression to complete (here, `bar.`). This approach fails however for infix calls, since completing `foo + bar.` starts by parsing `foo + bar`, which is a complete call expression, and so the code behaves as if completing `(foo + bar).` instead of `bar.`. This leads to the current problematic behaviour: ```julia julia> Complex(1, 3) + (4//5).#TAB im re ``` which would be correct for `(Complex(1, 3) + (4//5)).#TAB`, but here we expect ```julia julia> Complex(1, 3) + (4//5).#TAB den num ``` This PR fixes that by trying to detect infix calls. In the long term, all this ad-hoc and probably somewhat wrong string processing should be replaced by proper use of `JuliaSyntax` (as mentioned in #49294 (comment), #50817 (comment) and probably other places), but for now at least this fixes the regression. (cherry picked from commit e949236)
1 parent d117058 commit 110e9ba

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

stdlib/REPL/src/REPLCompletions.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,17 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff
997997
ex = Meta.parse(lookup_name, raise=false, depwarn=false)
998998
end
999999
isexpr(ex, :incomplete) && (ex = nothing)
1000+
elseif isexpr(ex, :call) && length(ex.args) > 1
1001+
isinfix = s[end] != ')'
1002+
# A complete call expression that does not finish with ')' is an infix call.
1003+
if !isinfix
1004+
# Handle infix call argument completion of the form bar + foo(qux).
1005+
frange, end_of_identifier = find_start_brace(@view s[1:prevind(s, end)])
1006+
isinfix = Meta.parse(@view(s[frange[1]:end]), raise=false, depwarn=false) == ex.args[end]
1007+
end
1008+
if isinfix
1009+
ex = ex.args[end]
1010+
end
10001011
end
10011012
end
10021013
append!(suggestions, complete_symbol(ex, name, ffunc, context_module))

stdlib/REPL/test/replcompletions.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ let ex = quote
2525
(::Test_y)() = "", ""
2626
unicode_αβγ = Test_y(1)
2727

28+
Base.:(+)(x::Test_x, y::Test_y) = Test_x(Test_y(x.xx.yy + y.yy))
2829
module CompletionFoo2
2930

3031
end
@@ -1889,3 +1890,17 @@ let s = "Issue49892(fal"
18891890
@test n in c
18901891
end
18911892
end
1893+
1894+
# issue #51194
1895+
for (s, compl) in (("2*CompletionFoo.nam", "named"),
1896+
(":a isa CompletionFoo.test!1", "test!12"),
1897+
("-CompletionFoo.Test_y(3).", "yy"),
1898+
("99 ⨷⁻ᵨ⁷ CompletionFoo.type_test.", "xx"),
1899+
("CompletionFoo.type_test + CompletionFoo.Test_y(2).", "yy"),
1900+
("(CompletionFoo.type_test + CompletionFoo.Test_y(2)).", "xx"),
1901+
("CompletionFoo.type_test + CompletionFoo.unicode_αβγ.", "yy"),
1902+
("(CompletionFoo.type_test + CompletionFoo.unicode_αβγ).", "xx"),
1903+
("foo'CompletionFoo.test!1", "test!12"))
1904+
c, r = test_complete(s)
1905+
@test only(c) == compl
1906+
end

0 commit comments

Comments
 (0)