@@ -15,7 +15,6 @@ import (
1515	"regexp" 
1616	"strings" 
1717
18- 	"golang.org/x/tools/go/ast/astutil" 
1918	"golang.org/x/tools/gopls/internal/cache" 
2019	"golang.org/x/tools/gopls/internal/cache/metadata" 
2120	"golang.org/x/tools/gopls/internal/cache/parsego" 
@@ -39,6 +38,7 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
3938	if  err  !=  nil  {
4039		return  nil , err 
4140	}
41+ 	cur , _  :=  pgf .Cursor .FindByPos (pos , pos ) // can't fail 
4242
4343	// Handle the case where the cursor is in an import. 
4444	importLocations , err  :=  importDefinition (ctx , snapshot , pkg , pgf , pos )
@@ -51,7 +51,7 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
5151
5252	// Handle the case where the cursor is in the package name. 
5353	// We use "<= End" to accept a query immediately after the package name. 
54- 	if  pgf .File  !=  nil  &&  pgf . File . Name . Pos ()  <=   pos   &&   pos   <=   pgf .File .Name . End ( ) {
54+ 	if  pgf .File  !=  nil  &&  internalastutil . NodeContains ( pgf .File .Name ,  pos ) {
5555		// If there's no package documentation, just use current file. 
5656		declFile  :=  pgf 
5757		for  _ , pgf  :=  range  pkg .CompiledGoFiles () {
@@ -86,14 +86,12 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
8686	}
8787
8888	// Handle definition requests for various special kinds of syntax node. 
89- 	path , _  :=  astutil .PathEnclosingInterval (pgf .File , pos , pos )
90- 	ancestors  :=  path [1 :]
91- 	switch  node  :=  path [0 ].(type ) {
89+ 	switch  node  :=  cur .Node ().(type ) {
9290	// Handle the case where the cursor is on a return statement by jumping to the result variables. 
9391	case  * ast.ReturnStmt :
9492		var  funcType  * ast.FuncType 
95- 		for  _ ,  n   :=  range  ancestors  {
96- 			switch  n  :=  n .(type ) {
93+ 		for  c   :=  range  cur . Enclosing ()  {
94+ 			switch  n  :=  c . Node () .(type ) {
9795			case  * ast.FuncLit :
9896				funcType  =  n .Type 
9997			case  * ast.FuncDecl :
@@ -128,14 +126,14 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
128126
129127		case  token .BREAK , token .CONTINUE :
130128			// Find innermost relevant ancestor for break/continue. 
131- 			for  i ,  n   :=  range  ancestors  {
132- 				if  isLabeled  &&   i + 1   <   len ( ancestors )  {
133- 					l , ok  :=  ancestors [ i + 1 ] .(* ast.LabeledStmt )
129+ 			for  c   :=  range  cur . Enclosing ()  {
130+ 				if  isLabeled  {
131+ 					l , ok  :=  c . Parent (). Node () .(* ast.LabeledStmt )
134132					if  ! (ok  &&  l .Label .Name  ==  label .Name ()) {
135133						continue 
136134					}
137135				}
138- 				switch  n .(type ) {
136+ 				switch  n   :=   c . Node () .(type ) {
139137				case  * ast.ForStmt , * ast.RangeStmt :
140138					var  start , end  token.Pos 
141139					if  node .Tok  ==  token .BREAK  {
@@ -164,12 +162,29 @@ func Definition(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, p
164162		}
165163	}
166164
167- 	// The general case: the cursor is on an identifier. 
168- 	_ , obj , _  :=  hoverDefinitionObjectAtPos (pkg .TypesInfo (), pgf , pos )
169- 	if  obj  ==  nil  {
165+ 	// The general case: the cursor is on (or near) an identifier. 
166+ 	objects , err  :=  objectsAt (pkg .TypesInfo (), cur )
167+ 	if  err  !=  nil  {
168+ 		return  nil , nil 
169+ 	}
170+ 	obj  :=  objects [0 ].obj 
171+ 	cur  =  objects [0 ].cur  // nearby 
172+ 	id , ok  :=  cur .Node ().(* ast.Ident )
173+ 	if  ! ok  {
174+ 		// objectsAt can return a non-Ident (e.g. ImportSpec), 
175+ 		// but we dealt with them earlier. Can't happen? 
170176		return  nil , nil 
171177	}
172178
179+ 	// If the query position was an embedded field, we want to jump 
180+ 	// to the field's type definition, not the field's definition (#42254). 
181+ 	if  v , ok  :=  obj .(* types.Var ); ok  &&  v .Embedded () {
182+ 		// types.Info.Uses contains the embedded field's *types.TypeName. 
183+ 		if  typeName  :=  pkg .TypesInfo ().Uses [id ]; typeName  !=  nil  {
184+ 			obj  =  typeName 
185+ 		}
186+ 	}
187+ 
173188	// Non-go (e.g. assembly) symbols 
174189	// 
175190	// When already at the definition of a Go function without 
@@ -304,57 +319,6 @@ func builtinDecl(ctx context.Context, snapshot *cache.Snapshot, obj types.Object
304319	return  pgf , ident , nil 
305320}
306321
307- // hoverDefinitionObjectAtPos returns the identifier and object referenced at the 
308- // specified position, which must be within the file pgf, for the purposes of 
309- // hover and definition operations. It returns a nil object if no 
310- // object was found at the given position. 
311- // 
312- // If the returned identifier is a type-switch implicit (i.e. the x in x := 
313- // e.(type)), the third result will be the type of the expression being 
314- // switched on (the type of e in the example). This facilitates workarounds for 
315- // limitations of the go/types API, which does not report an object for the 
316- // identifier x. 
317- // 
318- // For embedded fields, hoverDefinitionObjectAtPos returns the type name object rather 
319- // than the var (field) object. 
320- // 
321- // TODO(rfindley): this function exists to preserve the pre-existing behavior 
322- // of golang.Identifier. Eliminate this helper in favor of sharing 
323- // functionality with [objectsAt] and [pathEnclosingObjNode] 
324- // after choosing suitable primitives. 
325- func  hoverDefinitionObjectAtPos (info  * types.Info , pgf  * parsego.File , pos  token.Pos ) (* ast.Ident , types.Object , types.Type ) {
326- 	path  :=  pathEnclosingObjNode (pgf .File , pos )
327- 	if  len (path ) ==  0  {
328- 		return  nil , nil , nil 
329- 	}
330- 	if  id , ok  :=  path [0 ].(* ast.Ident ); ok  {
331- 		obj  :=  info .ObjectOf (id )
332- 		// If n is the var's declaring ident in a type switch 
333- 		// [i.e. the x in x := foo.(type)], it will not have an object. In this 
334- 		// case, set obj to the first implicit object (if any), and return the type 
335- 		// of the expression being switched on. 
336- 		// 
337- 		// The type switch may have no case clauses and thus no 
338- 		// implicit objects; this is a type error ("unused x"), 
339- 		if  obj  ==  nil  {
340- 			if  implicits , typ  :=  typeSwitchImplicits (info , path ); len (implicits ) >  0  {
341- 				return  id , implicits [0 ], typ 
342- 			}
343- 		}
344- 
345- 		// If the original position was an embedded field, we want to jump 
346- 		// to the field's type definition, not the field's definition. 
347- 		if  v , ok  :=  obj .(* types.Var ); ok  &&  v .Embedded () {
348- 			// types.Info.Uses contains the embedded field's *types.TypeName. 
349- 			if  typeName  :=  info .Uses [id ]; typeName  !=  nil  {
350- 				obj  =  typeName 
351- 			}
352- 		}
353- 		return  id , obj , nil 
354- 	}
355- 	return  nil , nil , nil 
356- }
357- 
358322// importDefinition returns locations defining a package referenced by the 
359323// import spec containing pos. 
360324// 
@@ -363,7 +327,7 @@ func importDefinition(ctx context.Context, s *cache.Snapshot, pkg *cache.Package
363327	var  imp  * ast.ImportSpec 
364328	for  _ , spec  :=  range  pgf .File .Imports  {
365329		// We use "<= End" to accept a query immediately after an ImportSpec. 
366- 		if  spec . Path . Pos ()  <=   pos   &&   pos   <=   spec .Path . End ( ) {
330+ 		if  internalastutil . NodeContains ( spec .Path ,  pos ) {
367331			imp  =  spec 
368332		}
369333	}
0 commit comments