Skip to content

fix(go) highlight the name of a method with a receiver - #4458

Open
alliasgher wants to merge 1 commit into
highlightjs:mainfrom
alliasgher:go-method-receiver-title
Open

fix(go) highlight the name of a method with a receiver#4458
alliasgher wants to merge 1 commit into
highlightjs:mainfrom
alliasgher:go-method-receiver-title

Conversation

@alliasgher

Copy link
Copy Markdown

Fixes #4196.

Describe the issue

func (c *exec.Cmd) Run() error gets no hljs-title on Run, while a plain func deferFunc(err *error) highlights fine.

The function mode contains a params sub-mode with endsParent: true, so the first parenthesised group ends the whole function mode. For a method, that first group is the receiver, so the mode terminates at the receiver's ) and TITLE_MODE never gets as far as the method name.

The fix

A separate receiver mode, placed before TITLE_MODE, which does not end its parent:

const RECEIVER = hljs.inherit(PARAMS, {
  begin: regex.concat(/\(/, regex.lookahead(/[^)]+\)\s*(?!func\b)[a-zA-Z_]\w*\s*\(/)),
  endsParent: false
});

I kept the grammar deliberately narrow rather than loosening func generally, since widening it risks auto-detection. The lookahead only fires for a non-empty parenthesised group that is directly followed by an identifier and another open paren, which is the method-declaration shape. A plain function's argument list is not followed by name(, so it never matches and behaves exactly as before.

The (?!func\b) is there for func middleware(h Handler) func(int32) int32: a return type can be followed by (, and without the guard that argument list would be misread as a receiver.

Testing

New markup test test/markup/go/methods.txt covering a pointer receiver, a value receiver, an anonymous receiver (*sync.Mutex), a generic receiver (s *Stack[T]), multiple return values, and the func-typed return above as a negative case. It fails on main and passes with this change.

Full suite: 1594 passing, and no existing test/markup/go/*.expect.txt changed, which is the check that plain functions are untouched. npm run lint and npm run lint-languages are clean.

Two limitations I did not try to fix, both pre-existing and equally true of plain functions today:

  • a method's own parameter list is now inside the params mode, so a string in a parameter default/array-length expression loses hljs-string — this makes methods consistent with plain functions rather than introducing a new inconsistency
  • methods with non-ASCII names are still not highlighted, since TITLE_MODE is ASCII-only

Checklist

  • Added markup tests
  • Updated the changelog at CHANGES.md

The function mode's params sub-mode has endsParent, so the first parenthesised
group closed the whole mode. For a method that group is the receiver, so the
mode ended at the receiver's closing paren and TITLE_MODE never reached the
method name.

Add a receiver mode that matches only a parenthesised group directly followed
by an identifier and another open paren, and which does not end its parent. A
plain function's argument list does not match that shape, so it keeps the old
behaviour, and a func-typed return such as func(int32) int32 is excluded
explicitly so it is still treated as a return type.

Fixes highlightjs#4196
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(Go) Method Highlighting

1 participant