@@ -392,15 +392,55 @@ func TestLinkContainsOffset(t *testing.T) {
392392
393393func TestLinkCloseOffset (t * testing.T ) {
394394 t .Parallel ()
395+ // Inline link via nil (exercises the l==nil path, identical to the
396+ // real production path where l!=nil, l.Reference==nil).
395397 // "[text](dest)\n": '[' 0, text 1-4, ']' 5, '(' 6, dest 7-10, ')' 11, '\n' 12.
396- // With nil link (inline path): after=5, source[5]=']' so i advances to 6,
397- // source[6]='(' triggers depth scan, ')' found at offset 11.
398398 src := []byte ("[text](dest)\n " )
399399 assert .Equal (t , 11 , linkCloseOffset (src , nil , 5 ))
400400
401401 // Newline before the closing ')' → -1.
402402 srcBroken := []byte ("[text](dest\n more\n " )
403403 assert .Equal (t , - 1 , linkCloseOffset (srcBroken , nil , 5 ))
404+
405+ // Shortcut reference [label]: close must land on the single ']'.
406+ root , b := parseDoc ("# T\n \n [label]\n \n [label]: https://x.com\n " )
407+ shortcut := firstLink (root )
408+ require .NotNil (t , shortcut )
409+ var shortcutAfter int
410+ _ = goldast .Walk (shortcut , func (n goldast.Node , entering bool ) (goldast.WalkStatus , error ) {
411+ if ! entering {
412+ return goldast .WalkContinue , nil
413+ }
414+ if tx , ok := n .(* goldast.Text ); ok {
415+ shortcutAfter = tx .Segment .Stop
416+ return goldast .WalkStop , nil
417+ }
418+ return goldast .WalkContinue , nil
419+ })
420+ off := linkCloseOffset (b , shortcut , shortcutAfter )
421+ assert .True (t , off >= 0 , "shortcut ref close offset must be ≥ 0" )
422+ assert .Equal (t , byte (']' ), b [off ], "shortcut ref must close at ']'" )
423+
424+ // Full reference [text][label]: close must land on the ']' of the label part.
425+ root2 , b2 := parseDoc ("# T\n \n [text][label]\n \n [label]: https://x.com\n " )
426+ full := firstLink (root2 )
427+ require .NotNil (t , full )
428+ var fullAfter int
429+ _ = goldast .Walk (full , func (n goldast.Node , entering bool ) (goldast.WalkStatus , error ) {
430+ if ! entering {
431+ return goldast .WalkContinue , nil
432+ }
433+ if tx , ok := n .(* goldast.Text ); ok {
434+ fullAfter = tx .Segment .Stop
435+ return goldast .WalkStop , nil
436+ }
437+ return goldast .WalkContinue , nil
438+ })
439+ off2 := linkCloseOffset (b2 , full , fullAfter )
440+ assert .True (t , off2 >= 0 , "full ref close offset must be ≥ 0" )
441+ assert .Equal (t , byte (']' ), b2 [off2 ], "full ref must close at ']' of label part" )
442+ // The close must be past the text-closing ']' (i.e., farther into the source).
443+ assert .Greater (t , off2 , fullAfter , "full ref close must be past the text bracket" )
404444}
405445
406446func TestScanForByte (t * testing.T ) {
@@ -461,6 +501,25 @@ func TestPiToLocate(t *testing.T) {
461501 assert .Equal (t , "x.md" , res .DirectiveTargetFile )
462502}
463503
504+ func TestPiToLocate_GlobInputSuppressed (t * testing.T ) {
505+ t .Parallel ()
506+ // A <?build?> inputs list item that is a glob pattern must NOT populate
507+ // DirectiveTargetFile — go-to-definition must not fire on a pattern.
508+ src := "# T\n \n <?build\n recipe: make\n inputs:\n - \" *.md\" \n outputs:\n - out.html\n ?>\n <?/build?>\n "
509+ root , b := parseDoc (src )
510+ pi := firstPI (root )
511+ require .NotNil (t , pi )
512+
513+ lines := bytes .Split (b , []byte ("\n " ))
514+ // Line 6 (1-based) is ` - "*.md"` — a glob pattern.
515+ res := piToLocate (pi , b , lines , 6 , 5 )
516+ assert .Equal (t , TokenDirectiveArg , res .Tag )
517+ assert .Equal (t , "build" , res .DirectiveName )
518+ assert .Equal (t , "inputs" , res .DirectiveArg )
519+ assert .Equal (t , "*.md" , res .DirectiveValue )
520+ assert .Equal (t , "" , res .DirectiveTargetFile , "glob pattern must not populate DirectiveTargetFile" )
521+ }
522+
464523func TestListItemValue (t * testing.T ) {
465524 t .Parallel ()
466525 v , ok := listItemValue (" - foo" )
@@ -542,4 +601,7 @@ func TestOffsetAt(t *testing.T) {
542601 assert .Equal (t , 5 , offsetAt (lines , 2 , 2 ))
543602 // Clamp: line < 1 → treated as line 1
544603 assert .Equal (t , 0 , offsetAt (lines , 0 , 1 ))
604+ // Clamp: col past end of line → clamped to line length.
605+ // Line 1 "abc" has length 3; col 99 → offset = 0 + 3 = 3.
606+ assert .Equal (t , 3 , offsetAt (lines , 1 , 99 ))
545607}
0 commit comments