@ttsc/lint 0.7.2 → 0.8.0-dev.20260505

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,67 +9,67 @@ type noUnsafeFinally struct{}
9
9
 
10
10
  func (noUnsafeFinally) Name() string { return "no-unsafe-finally" }
11
11
  func (noUnsafeFinally) Visits() []shimast.Kind {
12
- return []shimast.Kind{
13
- shimast.KindReturnStatement,
14
- shimast.KindBreakStatement,
15
- shimast.KindContinueStatement,
16
- shimast.KindThrowStatement,
17
- }
12
+ return []shimast.Kind{
13
+ shimast.KindReturnStatement,
14
+ shimast.KindBreakStatement,
15
+ shimast.KindContinueStatement,
16
+ shimast.KindThrowStatement,
17
+ }
18
18
  }
19
19
  func (noUnsafeFinally) Check(ctx *Context, node *shimast.Node) {
20
- finallyAncestor := walkToFinally(node)
21
- if finallyAncestor == nil {
22
- return
23
- }
24
- keyword := keywordOfControl(node)
25
- ctx.Report(node, "Unsafe usage of "+keyword+".")
20
+ finallyAncestor := walkToFinally(node)
21
+ if finallyAncestor == nil {
22
+ return
23
+ }
24
+ keyword := keywordOfControl(node)
25
+ ctx.Report(node, "Unsafe usage of "+keyword+".")
26
26
  }
27
27
 
28
28
  func walkToFinally(node *shimast.Node) *shimast.Node {
29
- cur := node.Parent
30
- for cur != nil {
31
- if isFunctionLikeKind(cur) || cur.Kind == shimast.KindSourceFile {
32
- return nil
33
- }
34
- if cur.Kind == shimast.KindBlock {
35
- grand := cur.Parent
36
- if grand != nil && grand.Kind == shimast.KindTryStatement {
37
- try := grand.AsTryStatement()
38
- if try != nil && try.FinallyBlock == cur {
39
- return cur
40
- }
41
- }
42
- }
43
- // `break` / `continue` inside an inner loop within finally
44
- // targets that loop and is therefore safe.
45
- switch cur.Kind {
46
- case shimast.KindForStatement,
47
- shimast.KindForInStatement,
48
- shimast.KindForOfStatement,
49
- shimast.KindWhileStatement,
50
- shimast.KindDoStatement,
51
- shimast.KindSwitchStatement:
52
- if node.Kind == shimast.KindBreakStatement || node.Kind == shimast.KindContinueStatement {
53
- return nil
54
- }
55
- }
56
- cur = cur.Parent
57
- }
58
- return nil
29
+ cur := node.Parent
30
+ for cur != nil {
31
+ if isFunctionLikeKind(cur) || cur.Kind == shimast.KindSourceFile {
32
+ return nil
33
+ }
34
+ if cur.Kind == shimast.KindBlock {
35
+ grand := cur.Parent
36
+ if grand != nil && grand.Kind == shimast.KindTryStatement {
37
+ try := grand.AsTryStatement()
38
+ if try != nil && try.FinallyBlock == cur {
39
+ return cur
40
+ }
41
+ }
42
+ }
43
+ // `break` / `continue` inside an inner loop within finally
44
+ // targets that loop and is therefore safe.
45
+ switch cur.Kind {
46
+ case shimast.KindForStatement,
47
+ shimast.KindForInStatement,
48
+ shimast.KindForOfStatement,
49
+ shimast.KindWhileStatement,
50
+ shimast.KindDoStatement,
51
+ shimast.KindSwitchStatement:
52
+ if node.Kind == shimast.KindBreakStatement || node.Kind == shimast.KindContinueStatement {
53
+ return nil
54
+ }
55
+ }
56
+ cur = cur.Parent
57
+ }
58
+ return nil
59
59
  }
60
60
 
61
61
  func keywordOfControl(node *shimast.Node) string {
62
- switch node.Kind {
63
- case shimast.KindReturnStatement:
64
- return "return"
65
- case shimast.KindBreakStatement:
66
- return "break"
67
- case shimast.KindContinueStatement:
68
- return "continue"
69
- case shimast.KindThrowStatement:
70
- return "throw"
71
- }
72
- return "control flow"
62
+ switch node.Kind {
63
+ case shimast.KindReturnStatement:
64
+ return "return"
65
+ case shimast.KindBreakStatement:
66
+ return "break"
67
+ case shimast.KindContinueStatement:
68
+ return "continue"
69
+ case shimast.KindThrowStatement:
70
+ return "throw"
71
+ }
72
+ return "control flow"
73
73
  }
74
74
 
75
75
  // no-useless-catch: `catch (err) { throw err; }` adds no behavior.
@@ -79,45 +79,45 @@ type noUselessCatch struct{}
79
79
  func (noUselessCatch) Name() string { return "no-useless-catch" }
80
80
  func (noUselessCatch) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindCatchClause} }
81
81
  func (noUselessCatch) Check(ctx *Context, node *shimast.Node) {
82
- clause := node.AsCatchClause()
83
- if clause == nil || clause.VariableDeclaration == nil || clause.Block == nil {
84
- return
85
- }
86
- binding := clause.VariableDeclaration.AsVariableDeclaration()
87
- if binding == nil {
88
- return
89
- }
90
- bindingName := identifierText(binding.Name())
91
- if bindingName == "" {
92
- return
93
- }
94
- block := clause.Block.AsBlock()
95
- if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
96
- return
97
- }
98
- stmt := block.Statements.Nodes[0]
99
- if stmt == nil || stmt.Kind != shimast.KindThrowStatement {
100
- return
101
- }
102
- throw := stmt.AsThrowStatement()
103
- if throw == nil {
104
- return
105
- }
106
- if identifierText(throw.Expression) != bindingName {
107
- return
108
- }
109
- // Ignore when the surrounding try-catch has a `finally` block — the
110
- // catch may exist solely to keep the finally semantics intact.
111
- if try := node.Parent; try != nil && try.Kind == shimast.KindTryStatement {
112
- tryStmt := try.AsTryStatement()
113
- if tryStmt != nil && tryStmt.FinallyBlock != nil {
114
- return
115
- }
116
- }
117
- ctx.Report(node, "Unnecessary try/catch wrapper.")
82
+ clause := node.AsCatchClause()
83
+ if clause == nil || clause.VariableDeclaration == nil || clause.Block == nil {
84
+ return
85
+ }
86
+ binding := clause.VariableDeclaration.AsVariableDeclaration()
87
+ if binding == nil {
88
+ return
89
+ }
90
+ bindingName := identifierText(binding.Name())
91
+ if bindingName == "" {
92
+ return
93
+ }
94
+ block := clause.Block.AsBlock()
95
+ if block == nil || block.Statements == nil || len(block.Statements.Nodes) != 1 {
96
+ return
97
+ }
98
+ stmt := block.Statements.Nodes[0]
99
+ if stmt == nil || stmt.Kind != shimast.KindThrowStatement {
100
+ return
101
+ }
102
+ throw := stmt.AsThrowStatement()
103
+ if throw == nil {
104
+ return
105
+ }
106
+ if identifierText(throw.Expression) != bindingName {
107
+ return
108
+ }
109
+ // Ignore when the surrounding try-catch has a `finally` block — the
110
+ // catch may exist solely to keep the finally semantics intact.
111
+ if try := node.Parent; try != nil && try.Kind == shimast.KindTryStatement {
112
+ tryStmt := try.AsTryStatement()
113
+ if tryStmt != nil && tryStmt.FinallyBlock != nil {
114
+ return
115
+ }
116
+ }
117
+ ctx.Report(node, "Unnecessary try/catch wrapper.")
118
118
  }
119
119
 
120
120
  func init() {
121
- Register(noUnsafeFinally{})
122
- Register(noUselessCatch{})
121
+ Register(noUnsafeFinally{})
122
+ Register(noUselessCatch{})
123
123
  }