We can overload getfield now along the lines of:
julia> struct Foo
end
julia> Base.propertynames(::Foo) = (:a,:b,:c)
julia> Base.getproperty(::Foo, s::Symbol) = s === :a ? 1 : s === :b ? 2 : s === :c
and while we do get tab completion if the value is assigned to a symbol, e.g.
julia> x = Foo()
Foo()
julia> x.<TAB>
a b c
it doesn't work for even slightly more complicated expressions, like:
julia> Foo().<TAB> # No results
julia> arr = Any[Foo(), 1]
julia> arr[1]. # No results
This is probably my main frustration when using the REPL with packages that make use of this features heavily (e.g. PyCall), since I rely on tab completion for discovery of ABIs that I'm not particularly familiar with.
I'm thinking we might be able to solve this by having the REPL completer perform type inference for a thunk of
propertynames(<expr>)
e.g. propertynames(Foo()) for the first example:
1 ─ %1 = Main.Foo()::Core.Compiler.Const(Foo(), false)
│ %2 = Main.propertynames(%1)::Core.Compiler.Const((:a, :b, :c), false)
└── return %2
The compiler knows what the result will be, so we should be able to use it.
The same strategy could work for the second example, but we'd need a mode where inference is allowed to read values out of global variables (of course those results couldn't be cached, etc.). We may also want to have a way to put a total time bound on inference to avoid blocking the interactive use case too much (or maybe even be able to cancel inference - e.g. if another key is pressed).
It seems pretty reasonable to me to just evaluate the whole expression before the dot. It would be very unusual to put side effects there.
I agree that it's unusual, but I also think it's dangerous. Think of things like
pop!(a).<TAB>
Is that perhaps bad style? yes, but I think it might be common enough that we shouldn't just evaluate it. Also, type inference might able to give answers even when just straight up evaluation can't (e.g. if you know the type and propertynames is always based on the type).
Eval-based completion would be useful and very robust but I'm against making it the default behavior, too. It'd be nice to add extra key bind like Ctrl+Shift+TAB to do this.