Skip to content

Commit 86121cf

Browse files
committed
fix(promise): resolve review comments
1 parent 2a97063 commit 86121cf

3 files changed

Lines changed: 73 additions & 12 deletions

File tree

internal/plugins/promise/rules/no_nesting/no_nesting.go

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ func isPromiseCallback(node *ast.Node) bool {
3030
return isThenOrCatchCall(parent)
3131
}
3232

33-
// walkIdentifiers calls fn for each identifier name found anywhere in node's
33+
// walkIdentifiers calls fn for each identifier node found anywhere in node's
3434
// subtree, stopping early across the whole traversal if fn returns true.
35-
func walkIdentifiers(node *ast.Node, fn func(name string) bool) bool {
35+
func walkIdentifiers(node *ast.Node, fn func(identNode *ast.Node) bool) bool {
3636
if node == nil {
3737
return false
3838
}
3939
if node.Kind == ast.KindIdentifier {
40-
return fn(node.AsIdentifier().Text)
40+
return fn(node)
4141
}
4242
found := false
4343
node.ForEachChild(func(child *ast.Node) bool {
@@ -61,18 +61,52 @@ func argsContainRef(callNode *ast.Node, fn *ast.Node) bool {
6161
return false
6262
}
6363
body := fn.Body()
64+
boundary := fn
65+
if body != nil {
66+
boundary = body
67+
}
6468
for _, arg := range args.Nodes {
6569
found := false
66-
walkIdentifiers(arg, func(name string) bool {
67-
if utils.HasShadowingParameter(fn, name) {
68-
found = true
69-
return true
70+
walkIdentifiers(arg, func(identNode *ast.Node) bool {
71+
if utils.IsNonReferenceIdentifier(identNode) {
72+
return false
73+
}
74+
75+
name := identNode.AsIdentifier().Text
76+
77+
if name == "arguments" {
78+
if utils.IsNameShadowedBetween(identNode, boundary, name) {
79+
return false
80+
}
81+
isArgumentsShadowed := false
82+
for curr := identNode.Parent; curr != nil && curr != fn; curr = curr.Parent {
83+
if ast.IsFunctionLikeDeclaration(curr) && curr.Kind != ast.KindArrowFunction {
84+
isArgumentsShadowed = true
85+
break
86+
}
87+
}
88+
if isArgumentsShadowed {
89+
return false
90+
}
91+
if fn.Kind != ast.KindArrowFunction {
92+
found = true
93+
return true
94+
}
95+
return false
96+
}
97+
98+
hasParam := utils.HasShadowingParameter(fn, name)
99+
hasDecl := body != nil && (utils.HasShadowingDeclaration(body, name) || utils.HasHoistedVarDeclaration(body, name))
100+
if !hasParam && !hasDecl {
101+
return false
70102
}
71-
if body != nil && (utils.HasShadowingDeclaration(body, name) || utils.HasHoistedVarDeclaration(body, name)) {
72-
found = true
73-
return true
103+
104+
if utils.IsNameShadowedBetween(identNode, boundary, name) {
105+
return false
74106
}
75-
return false
107+
108+
found = true
109+
return true
76110
})
77111
if found {
78112
return true

internal/plugins/promise/rules/no_nesting/no_nesting_extras_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ func TestNoNestingExtras(t *testing.T) {
104104
{Code: `doThing().then(function(x) {
105105
return { get val() { return a.then(x) } };
106106
})`},
107+
108+
// ---- Dimension 4: implicit arguments binding in non-arrow callback ----
109+
{Code: `doThing().then(function() { return foo.then(() => use(arguments)) })`},
107110
},
108111
[]rule_tester.InvalidTestCase{
109112
// ---- Dimension 4: parenthesized callback — still reports inner .then ----
@@ -197,6 +200,30 @@ func TestNoNestingExtras(t *testing.T) {
197200
Code: `doThing().catch(function() { a.catch() })`,
198201
Errors: []rule_tester.InvalidTestCaseError{{MessageId: "avoidNesting", Line: 1}},
199202
},
203+
204+
// ---- Dimension 4: property access name is not a reference to outer binding ----
205+
{
206+
Code: `doThing().then(user => getProfile().then(p => p.user))`,
207+
Errors: []rule_tester.InvalidTestCaseError{{MessageId: "avoidNesting", Line: 1}},
208+
},
209+
210+
// ---- Dimension 4: object key is not a reference to outer binding ----
211+
{
212+
Code: `doThing().then(user => getProfile().then(p => ({ user: 1 })))`,
213+
Errors: []rule_tester.InvalidTestCaseError{{MessageId: "avoidNesting", Line: 1}},
214+
},
215+
216+
// ---- Dimension 4: inner parameter shadowing the outer binding ----
217+
{
218+
Code: `doThing().then(a => inner.then(a => use(a)))`,
219+
Errors: []rule_tester.InvalidTestCaseError{{MessageId: "avoidNesting", Line: 1}},
220+
},
221+
222+
// ---- Dimension 4: implicit arguments binding shadowed by nested non-arrow callback ----
223+
{
224+
Code: `doThing().then(function() { return foo.then(function() { use(arguments) }) })`,
225+
Errors: []rule_tester.InvalidTestCaseError{{MessageId: "avoidNesting", Line: 1}},
226+
},
200227
},
201228
)
202229
}

packages/rslint/src/configs/promise.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const recommended: RslintConfigEntry = {
1010
'promise/param-names': 'error',
1111
'promise/catch-or-return': 'error',
1212
// 'promise/no-native': 'off', // not implemented
13-
'promise/no-nesting': 'warn',
13+
// 'promise/no-nesting': 'warn', // not implemented
1414
// 'promise/no-promise-in-callback': 'warn', // not implemented
1515
// 'promise/no-callback-in-promise': 'warn', // not implemented
1616
'promise/avoid-new': 'off',

0 commit comments

Comments
 (0)