@@ -96,76 +96,11 @@ func insertDeclsAfter(ctx context.Context, snapshot *cache.Snapshot, mp *metadat
9696 return nil , nil , bug .Errorf ("can't find metadata for file %s among dependencies of %s" , declPGF .URI , mp )
9797 }
9898
99- // Build import environment for the declaring file.
100- // (typesinternal.FileQualifier works only for complete
101- // import mappings, and requires types.)
102- importEnv := make (map [ImportPath ]string ) // value is local name
103- for _ , imp := range declPGF .File .Imports {
104- importPath := metadata .UnquoteImportPath (imp )
105- var name string
106- if imp .Name != nil {
107- name = imp .Name .Name
108- if name == "_" {
109- continue
110- } else if name == "." {
111- name = "" // see types.Qualifier
112- }
113- } else {
114- // Use the correct name from the metadata of the imported
115- // package---not a guess based on the import path.
116- mp := snapshot .Metadata (declMeta .DepsByImpPath [importPath ])
117- if mp == nil {
118- continue // can't happen?
119- }
120- name = string (mp .Name )
121- }
122- importEnv [importPath ] = name // latest alias wins
99+ newImports := make ([]newImport , 0 , len (declPGF .File .Imports ))
100+ qual := newNamedImportQual (declPGF , snapshot , declMeta , sym , & newImports )
101+ if len (newImports ) != 0 {
102+ println ()
123103 }
124-
125- // Create a package name qualifier that uses the
126- // locally appropriate imported package name.
127- // It records any needed new imports.
128- // TODO(adonovan): factor with golang.FormatVarType?
129- //
130- // Prior to CL 469155 this logic preserved any renaming
131- // imports from the file that declares the interface
132- // method--ostensibly the preferred name for imports of
133- // frequently renamed packages such as protobufs.
134- // Now we use the package's declared name. If this turns out
135- // to be a mistake, then use parseHeader(si.iface.Pos()).
136- //
137- type newImport struct { name , importPath string }
138- var newImports []newImport // for AddNamedImport
139- qual := func (pkg * types.Package ) string {
140- // TODO(adonovan): don't ignore vendor prefix.
141- //
142- // Ignore the current package import.
143- if pkg .Path () == sym .Pkg ().Path () {
144- return ""
145- }
146-
147- importPath := ImportPath (pkg .Path ())
148- name , ok := importEnv [importPath ]
149- if ! ok {
150- // Insert new import using package's declared name.
151- //
152- // TODO(adonovan): resolve conflict between declared
153- // name and existing file-level (declPGF.File.Imports)
154- // or package-level (sym.Pkg.Scope) decls by
155- // generating a fresh name.
156- name = pkg .Name ()
157- importEnv [importPath ] = name
158- new := newImport {importPath : string (importPath )}
159- // For clarity, use a renaming import whenever the
160- // local name does not match the path's last segment.
161- if name != pathpkg .Base (trimVersionSuffix (new .importPath )) {
162- new .name = name
163- }
164- newImports = append (newImports , new )
165- }
166- return name
167- }
168-
169104 // Compute insertion point for new declarations:
170105 // after the top-level declaration enclosing the (package-level) type.
171106 insertOffset , err := safetoken .Offset (declPGF .Tok , declPGF .File .End ())
@@ -252,7 +187,7 @@ func trimVersionSuffix(path string) string {
252187 return path
253188}
254189
255- func insertStructField (ctx context.Context , snapshot * cache.Snapshot , meta * metadata.Package , fieldInfo * stubmethods.StructFieldInfo ) (* token.FileSet , * analysis.SuggestedFix , error ) {
190+ func insertStructField (ctx context.Context , snapshot * cache.Snapshot , mp * metadata.Package , fieldInfo * stubmethods.StructFieldInfo ) (* token.FileSet , * analysis.SuggestedFix , error ) {
256191 if fieldInfo == nil {
257192 return nil , nil , fmt .Errorf ("no field info provided" )
258193 }
@@ -284,6 +219,15 @@ func insertStructField(ctx context.Context, snapshot *cache.Snapshot, meta *meta
284219 return nil , nil , fmt .Errorf ("could not find struct definition" )
285220 }
286221
222+ // Find metadata for the symbol's declaring package
223+ // as we'll need its import mapping.
224+ declMeta := findFileInDeps (snapshot , mp , declPGF .URI )
225+ if declMeta == nil {
226+ return nil , nil , bug .Errorf ("can't find metadata for file %s among dependencies of %s" , declPGF .URI , mp )
227+ }
228+
229+ qual := newNamedImportQual (declPGF , snapshot , declMeta , fieldInfo .Named .Obj (), new ([]newImport ))
230+
287231 // find the position to insert the new field (end of struct fields)
288232 insertPos := structType .Fields .Closing - 1
289233 if insertPos == structType .Fields .Opening {
@@ -292,7 +236,7 @@ func insertStructField(ctx context.Context, snapshot *cache.Snapshot, meta *meta
292236 }
293237
294238 var buf bytes.Buffer
295- if err := fieldInfo .Emit (& buf , types . RelativeTo ( fieldInfo . Named . Obj (). Pkg ()) ); err != nil {
239+ if err := fieldInfo .Emit (& buf , qual ); err != nil {
296240 return nil , nil , err
297241 }
298242
@@ -312,3 +256,78 @@ func insertStructField(ctx context.Context, snapshot *cache.Snapshot, meta *meta
312256 TextEdits : []analysis.TextEdit {textEdit },
313257 }, nil
314258}
259+
260+ type newImport struct {
261+ name string
262+ importPath string
263+ }
264+
265+ func newNamedImportQual (declPGF * parsego.File , snapshot * cache.Snapshot , declMeta * metadata.Package , sym types.Object , newImports * []newImport ) func (* types.Package ) string {
266+ // Build import environment for the declaring file.
267+ // (typesinternal.FileQualifier works only for complete
268+ // import mappings, and requires types.)
269+ importEnv := make (map [ImportPath ]string ) // value is local name
270+ for _ , imp := range declPGF .File .Imports {
271+ importPath := metadata .UnquoteImportPath (imp )
272+ var name string
273+ if imp .Name != nil {
274+ name = imp .Name .Name
275+ if name == "_" {
276+ continue
277+ } else if name == "." {
278+ name = "" // see types.Qualifier
279+ }
280+ } else {
281+ // Use the correct name from the metadata of the imported
282+ // package---not a guess based on the import path.
283+ mp := snapshot .Metadata (declMeta .DepsByImpPath [importPath ])
284+ if mp == nil {
285+ continue // can't happen?
286+ }
287+ name = string (mp .Name )
288+ }
289+ importEnv [importPath ] = name // latest alias wins
290+ }
291+
292+ // Create a package name qualifier that uses the
293+ // locally appropriate imported package name.
294+ // It records any needed new imports.
295+ // TODO(adonovan): factor with golang.FormatVarType?
296+ //
297+ // Prior to CL 469155 this logic preserved any renaming
298+ // imports from the file that declares the interface
299+ // method--ostensibly the preferred name for imports of
300+ // frequently renamed packages such as protobufs.
301+ // Now we use the package's declared name. If this turns out
302+ // to be a mistake, then use parseHeader(si.iface.Pos()).
303+ //
304+ return func (pkg * types.Package ) string {
305+ // TODO(adonovan): don't ignore vendor prefix.
306+ //
307+ // Ignore the current package import.
308+ if pkg .Path () == sym .Pkg ().Path () {
309+ return ""
310+ }
311+
312+ importPath := ImportPath (pkg .Path ())
313+ name , ok := importEnv [importPath ]
314+ if ! ok {
315+ // Insert new import using package's declared name.
316+ //
317+ // TODO(adonovan): resolve conflict between declared
318+ // name and existing file-level (declPGF.File.Imports)
319+ // or package-level (sym.Pkg.Scope) decls by
320+ // generating a fresh name.
321+ name = pkg .Name ()
322+ importEnv [importPath ] = name
323+ new := newImport {importPath : string (importPath )}
324+ // For clarity, use a renaming import whenever the
325+ // local name does not match the path's last segment.
326+ if name != pathpkg .Base (trimVersionSuffix (new .importPath )) {
327+ new .name = name
328+ }
329+ * newImports = append (* newImports , new )
330+ }
331+ return name
332+ }
333+ }
0 commit comments