Conversation
Align GetFunctionHeadLoc with typescript-eslint's getFunctionHeadLoc, which skips leading decorators on MethodDefinition / PropertyDefinition when computing the head range. The previous implementation used node.Pos() directly, which in tsgo sits before the first decorator, so rules like explicit-function-return-type reported the decorator line/column instead of the method itself. Added a shared nodeStartSkippingDecorators helper and threaded it through the method / getter / setter / constructor branches and the property-initializer branches for arrow and function expressions.
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates the GetFunctionHeadLoc utility to exclude leading decorators from the reported range of class members, aligning the behavior with typescript-eslint. A new helper function nodeStartSkippingDecorators was introduced, and existing tests for require_yield and explicit_function_return_type were updated to reflect the adjusted reporting locations. A review comment suggests initializing the search position for function parameters from the start of the node after decorators to avoid incorrectly matching parentheses within decorator factories.
Address Gemini Code Assist review: when the member is a nameless Constructor and it carries a decorator factory (e.g. @dec()), using node.Pos() as the parameter-paren search origin matches the `(` of the decorator factory first and produces an inverted range. Anchor the scan at the first token after the decorators instead, keeping the prior behaviour for named methods/getters/setters via the name.End() override. Adds a utils-level regression test that asserts the range spans just the `constructor` keyword. Also sync the `require-yield` JS mirror test (and its snapshot) with the Go expectations updated in the previous commit — the columns now land after the decorators instead of on `@`.
3f0bda5 to
f697667
Compare
simplyme0823
approved these changes
Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GetFunctionHeadLocis supposed to mirror typescript-eslint'sgetFunctionHeadLoc, which explicitly skips leading decorators onMethodDefinition/PropertyDefinitionwhen computing the reportedhead range. The old implementation used
node.Pos()/TrimNodeTextRangedirectly, and in tsgo that sits before the first decorator — so any
rule using this helper (
explicit-function-return-type,require-yield,accessor-pairs,no-misused-promises) reported the decorator line/columninstead of the method/property itself.
Concretely, for
```ts
class HookLifeCycle {
@LifecycleHook()
async didLoad() { ... }
}
```
ESLint reports line 4 col 3 (at
async); rslint reported line 3 col 3(at
@LifecycleHook).Fix: new
nodeStartSkippingDecoratorshelper walksnode.Modifiers()to find the last decorator and starts the range at the next token.
It is plumbed through every branch of
GetFunctionHeadLocwhere the"start" came from the decorated node or its property parent.
Related Links
n/a
Checklist