@@ -980,7 +980,10 @@ function project_deps_get_completion_candidates(pkgstarts::String, project_file:
980
980
return Completion[PackageCompletion (name) for name in loading_candidates]
981
981
end
982
982
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 )
984
987
ex = nothing
985
988
if comp_keywords
986
989
append! (suggestions, complete_keyword (name))
@@ -1022,10 +1025,41 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff
1022
1025
if something (findlast (in (non_identifier_chars), s), 0 ) < something (findlast (isequal (' .' ), s), 0 )
1023
1026
lookup_name, name = rsplit (s, " ." , limit= 2 )
1024
1027
name = String (name)
1025
-
1026
1028
ex = Meta. parse (lookup_name, raise= false , depwarn= false )
1027
1029
end
1028
1030
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
1029
1063
elseif isexpr (ex, :call ) && length (ex. args) > 1
1030
1064
isinfix = s[end ] != ' )'
1031
1065
# 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
1106
1140
ok && return ret
1107
1141
startpos = first (varrange) + 4
1108
1142
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)
1111
1146
elseif inc_tag === :cmd
1112
1147
# TODO : should this call shell_completions instead of partially reimplementing it?
1113
1148
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
1255
1290
end
1256
1291
end
1257
1292
end
1258
- ffunc = (mod,x) -> (Base . isbindingresolved (mod, x) && isdefined (mod, x) && isa ( getfield (mod, x), Module))
1293
+ ffunc = module_filter
1259
1294
comp_keywords = false
1260
1295
end
1261
1296
1262
1297
startpos == 0 && (pos = - 1 )
1263
1298
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)
1266
1302
end
1267
1303
1304
+ module_filter (mod:: Module , x:: Symbol ) =
1305
+ Base. isbindingresolved (mod, x) && isdefined (mod, x) && isa (getglobal (mod, x), Module)
1306
+
1268
1307
function shell_completions (string, pos)
1269
1308
# First parse everything up to the current position
1270
1309
scs = string[1 : pos]
0 commit comments