@@ -980,7 +980,10 @@ function project_deps_get_completion_candidates(pkgstarts::String, project_file:
980980 return Completion[PackageCompletion (name) for name in loading_candidates]
981981end
982982
983- function complete_identifiers! (suggestions:: Vector{Completion} , @nospecialize (ffunc:: Function ), context_module:: Module , string:: String , name:: String , pos:: Int , dotpos:: Int , startpos:: Int , comp_keywords= false )
983+ function complete_identifiers! (suggestions:: Vector{Completion} , @nospecialize (ffunc),
984+ context_module:: Module , string:: String , name:: String ,
985+ pos:: Int , dotpos:: Int , startpos:: Int ;
986+ comp_keywords= false )
984987 ex = nothing
985988 if comp_keywords
986989 append! (suggestions, complete_keyword (name))
@@ -1022,10 +1025,41 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff
10221025 if something (findlast (in (non_identifier_chars), s), 0 ) < something (findlast (isequal (' .' ), s), 0 )
10231026 lookup_name, name = rsplit (s, " ." , limit= 2 )
10241027 name = String (name)
1025-
10261028 ex = Meta. parse (lookup_name, raise= false , depwarn= false )
10271029 end
10281030 isexpr (ex, :incomplete ) && (ex = nothing )
1031+ elseif isexpr (ex, (:using , :import ))
1032+ arg1 = ex. args[1 ]
1033+ if isexpr (arg1, :.)
1034+ # We come here for cases like:
1035+ # - `string`: "using Mod1.Mod2.M"
1036+ # - `ex`: :(using Mod1.Mod2)
1037+ # - `name`: "M"
1038+ # Now we transform `ex` to `:(Mod1.Mod2)` to allow `complete_symbol` to
1039+ # complete for inner modules whose name starts with `M`.
1040+ # Note that `ffunc` is set to `module_filter` within `completions`
1041+ ex = nothing
1042+ firstdot = true
1043+ for arg = arg1. args
1044+ if arg === :.
1045+ # override `context_module` if multiple `.` accessors are used
1046+ if firstdot
1047+ firstdot = false
1048+ else
1049+ context_module = parentmodule (context_module)
1050+ end
1051+ elseif arg isa Symbol
1052+ if ex === nothing
1053+ ex = arg
1054+ else
1055+ ex = Expr (:., out, QuoteNode (arg))
1056+ end
1057+ else # invalid expression
1058+ ex = nothing
1059+ break
1060+ end
1061+ end
1062+ end
10291063 elseif isexpr (ex, :call ) && length (ex. args) > 1
10301064 isinfix = s[end ] != ' )'
10311065 # A complete call expression that does not finish with ')' is an infix call.
@@ -1106,8 +1140,9 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
11061140 ok && return ret
11071141 startpos = first (varrange) + 4
11081142 dotpos = something (findprev (isequal (' .' ), string, first (varrange)- 1 ), 0 )
1109- return complete_identifiers! (Completion[], ffunc, context_module, string,
1110- string[startpos: pos], pos, dotpos, startpos)
1143+ name = string[startpos: pos]
1144+ return complete_identifiers! (Completion[], ffunc, context_module, string, name, pos,
1145+ dotpos, startpos)
11111146 elseif inc_tag === :cmd
11121147 # TODO : should this call shell_completions instead of partially reimplementing it?
11131148 let m = match (r" [\t\n\r\" `><=*?|]| (?!\\ )" , reverse (partial)) # fuzzy shell_parse in reverse
@@ -1255,16 +1290,20 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
12551290 end
12561291 end
12571292 end
1258- ffunc = (mod,x) -> (Base . isbindingresolved (mod, x) && isdefined (mod, x) && isa ( getfield (mod, x), Module))
1293+ ffunc = module_filter
12591294 comp_keywords = false
12601295 end
12611296
12621297 startpos == 0 && (pos = - 1 )
12631298 dotpos < startpos && (dotpos = startpos - 1 )
1264- return complete_identifiers! (suggestions, ffunc, context_module, string,
1265- name, pos, dotpos, startpos, comp_keywords)
1299+ return complete_identifiers! (suggestions, ffunc, context_module, string, name, pos,
1300+ dotpos, startpos;
1301+ comp_keywords)
12661302end
12671303
1304+ module_filter (mod:: Module , x:: Symbol ) =
1305+ Base. isbindingresolved (mod, x) && isdefined (mod, x) && isa (getglobal (mod, x), Module)
1306+
12681307function shell_completions (string, pos)
12691308 # First parse everything up to the current position
12701309 scs = string[1 : pos]
0 commit comments