@@ -32,7 +32,7 @@ if len(s:goarch) == 0
32
32
endif
33
33
endif
34
34
35
- function ! go#package#Paths () abort
35
+ function ! s: paths () abort
36
36
let dirs = []
37
37
38
38
if ! exists (" s:goroot" )
@@ -58,6 +58,58 @@ function! go#package#Paths() abort
58
58
return dirs
59
59
endfunction
60
60
61
+ function ! s: module () abort
62
+ let [l: out , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -m' , ' -f' , ' {{.Dir}}' ])
63
+ if l: err != 0
64
+ return {}
65
+ endif
66
+ let l: dir = split (l: out , ' \n' )[0 ]
67
+
68
+ let [l: out , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -m' , ' -f' , ' {{.Path}}' ])
69
+ if l: err != 0
70
+ return {}
71
+ endif
72
+ let l: path = split (l: out , ' \n' )[0 ]
73
+
74
+ return {' dir' : l: dir , ' path' : l: path }
75
+ endfunction
76
+
77
+ function ! s: vendordirs () abort
78
+ let l: vendorsuffix = go#util#PathSep () . ' vendor'
79
+ let l: module = s: module ()
80
+ if empty (l: module )
81
+ let [l: root , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -f' , ' {{.Root}}' ])
82
+ if l: err != 0
83
+ return []
84
+ endif
85
+ let l: root = split (l: root , ' \n' )[0 ] . go#util#PathSep () . ' src'
86
+
87
+ let [l: dir , l: err ] = go#util#ExecInDir ([' go' , ' list' , ' -f' , ' {{.Dir}}' ])
88
+ if l: err != 0
89
+ return []
90
+ endif
91
+ let l: dir = split (l: dir , ' \n' )[0 ]
92
+
93
+ let l: vendordirs = []
94
+ while l: dir != l: root
95
+ let l: vendordir = l: dir . l: vendorsuffix
96
+ if isdirectory (l: vendordir )
97
+ let l: vendordirs = add (l: vendordirs , l: vendordir )
98
+ endif
99
+
100
+ let l: dir = fnamemodify (l: dir , ' :h' )
101
+ endwhile
102
+
103
+ return l: vendordirs
104
+ endif
105
+
106
+ let l: vendordir = l: module .dir . l: vendorsuffix
107
+ if ! isdirectory (l: vendordir )
108
+ return []
109
+ endif
110
+ return [l: vendordir ]
111
+ endfunction
112
+
61
113
let s: import_paths = {}
62
114
" ImportPath returns the import path of the package for current buffer.
63
115
function ! go#package#ImportPath () abort
@@ -144,33 +196,80 @@ function! go#package#Complete(ArgLead, CmdLine, CursorPos) abort
144
196
return go#package#CompleteMembers (words[1 ], words[2 ])
145
197
endif
146
198
147
- let dirs = go#package#Paths ()
199
+ let dirs = s: paths ()
200
+ let module = s: module ()
148
201
149
- if len (dirs) == 0
202
+ if len (dirs) == 0 && empty (module)
150
203
" should not happen
151
204
return []
152
205
endif
153
206
207
+ let vendordirs = s: vendordirs ()
208
+
154
209
let ret = {}
155
210
for dir in dirs
156
211
" this may expand to multiple lines
157
212
let root = split (expand (dir . ' /pkg/' . s: goos . ' _' . s: goarch ), " \n " )
158
- call add (root, expand (dir . ' /src' ))
159
- for r in root
160
- for i in split (globpath (r , a: ArgLead .' *' ), " \n " )
161
- if isdirectory (i )
162
- let i .= ' /'
163
- elseif i !~ ' \.a$'
213
+ let root = add (root, expand (dir . ' /src' ), )
214
+ let root = extend (root, vendordirs)
215
+ let root = add (root, module)
216
+ for item in root
217
+ " item may be a dictionary when operating in a module.
218
+ if type (item) == type ({})
219
+ if empty (item)
164
220
continue
165
221
endif
166
- let i = substitute (substitute (i [len (r )+ 1 :], ' [\\]' , ' /' , ' g' ),
222
+ let dir = item.dir
223
+ let path = item.path
224
+ else
225
+ let dir = item
226
+ let path = item
227
+ endif
228
+
229
+ if ! empty (module) && dir == # module.dir
230
+ if stridx (a: ArgLead , module.path ) == 0
231
+ if len (a: ArgLead ) != len (module.path )
232
+ let glob = globpath (module.dir , substitute (a: ArgLead , module.path . ' /\?' , ' ' , ' ' ).' *' )
233
+ else
234
+ let glob = module.dir
235
+ endif
236
+ elseif stridx (module.path , a: ArgLead ) == 0 && stridx (module.path , ' /' , len (a: ArgLead )) < 0
237
+ " use the module directory when a:ArgLead is contained in
238
+ " module.path and module.path does not have any path segments after
239
+ " a:ArgLead.
240
+ let glob = module.dir
241
+ else
242
+ continue
243
+ endif
244
+ else
245
+ let glob = globpath (dir , a: ArgLead .' *' )
246
+ endif
247
+ for candidate in split (glob )
248
+ if isdirectory (candidate)
249
+ " TODO(bc): use wildignore instead of filtering out vendor
250
+ " directories manually?
251
+ if fnamemodify (candidate, ' :t' ) == ' vendor'
252
+ continue
253
+ endif
254
+ let candidate .= ' /'
255
+ elseif candidate !~ ' \.a$'
256
+ continue
257
+ endif
258
+
259
+ if dir !=# path
260
+ let candidate = substitute (candidate, ' ^' . dir , path , ' g' )
261
+ else
262
+ let candidate = candidate[len (dir )+ 1 :]
263
+ endif
264
+ " replace a backslash with a forward slash and drop .a suffixes
265
+ let candidate = substitute (substitute (candidate, ' [\\]' , ' /' , ' g' ),
167
266
\ ' \.a$' , ' ' , ' g' )
168
267
169
268
" without this the result can have duplicates in form of
170
269
" 'encoding/json' and '/encoding/json/'
171
- let i = go#util#StripPathSep (i )
270
+ let candidate = go#util#StripPathSep (candidate )
172
271
173
- let ret [i ] = i
272
+ let ret [candidate ] = candidate
174
273
endfor
175
274
endfor
176
275
endfor
0 commit comments