@ttsc/lint 0.7.2 → 0.7.3

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.
package/plugin/host.go CHANGED
@@ -10,35 +10,35 @@
10
10
  package main
11
11
 
12
12
  import (
13
- "context"
14
- "errors"
15
- "fmt"
16
- "path/filepath"
13
+ "context"
14
+ "errors"
15
+ "fmt"
16
+ "path/filepath"
17
17
 
18
- shimast "github.com/microsoft/typescript-go/shim/ast"
19
- "github.com/microsoft/typescript-go/shim/bundled"
20
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
21
- shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
22
- shimcore "github.com/microsoft/typescript-go/shim/core"
23
- "github.com/microsoft/typescript-go/shim/tsoptions"
24
- "github.com/microsoft/typescript-go/shim/vfs/cachedvfs"
25
- "github.com/microsoft/typescript-go/shim/vfs/osvfs"
18
+ shimast "github.com/microsoft/typescript-go/shim/ast"
19
+ "github.com/microsoft/typescript-go/shim/bundled"
20
+ shimchecker "github.com/microsoft/typescript-go/shim/checker"
21
+ shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
22
+ shimcore "github.com/microsoft/typescript-go/shim/core"
23
+ "github.com/microsoft/typescript-go/shim/tsoptions"
24
+ "github.com/microsoft/typescript-go/shim/vfs/cachedvfs"
25
+ "github.com/microsoft/typescript-go/shim/vfs/osvfs"
26
26
  )
27
27
 
28
28
  // program bundles the tsgo Program with the parsed config and a checker
29
29
  // release callback so the orchestration code can clean up after itself.
30
30
  type program struct {
31
- cwd string
32
- tsProgram *shimcompiler.Program
33
- parsed *tsoptions.ParsedCommandLine
34
- checker *shimchecker.Checker
35
- releaseChecker func()
31
+ cwd string
32
+ tsProgram *shimcompiler.Program
33
+ parsed *tsoptions.ParsedCommandLine
34
+ checker *shimchecker.Checker
35
+ releaseChecker func()
36
36
  }
37
37
 
38
38
  type loadProgramOptions struct {
39
- forceEmit bool
40
- forceNoEmit bool
41
- outDir string
39
+ forceEmit bool
40
+ forceNoEmit bool
41
+ outDir string
42
42
  }
43
43
 
44
44
  // loadProgram parses the given tsconfig, builds a Program, and acquires a
@@ -48,143 +48,143 @@ type loadProgramOptions struct {
48
48
  // before the program is created so `--noEmit` and friends behave like
49
49
  // they do in `ttsc check`.
50
50
  func loadProgram(cwd, tsconfigPath string, options loadProgramOptions) (*program, []*shimast.Diagnostic, error) {
51
- if !filepath.IsAbs(cwd) {
52
- abs, err := filepath.Abs(cwd)
53
- if err != nil {
54
- return nil, nil, fmt.Errorf("loadProgram: cwd: %w", err)
55
- }
56
- cwd = abs
57
- }
58
- resolved := tsconfigPath
59
- if !filepath.IsAbs(resolved) {
60
- resolved = filepath.Join(cwd, resolved)
61
- }
51
+ if !filepath.IsAbs(cwd) {
52
+ abs, err := filepath.Abs(cwd)
53
+ if err != nil {
54
+ return nil, nil, fmt.Errorf("loadProgram: cwd: %w", err)
55
+ }
56
+ cwd = abs
57
+ }
58
+ resolved := tsconfigPath
59
+ if !filepath.IsAbs(resolved) {
60
+ resolved = filepath.Join(cwd, resolved)
61
+ }
62
62
 
63
- fs := bundled.WrapFS(cachedvfs.From(osvfs.FS()))
64
- host := shimcompiler.NewCompilerHost(cwd, fs, bundled.LibPath(), nil, nil)
63
+ fs := bundled.WrapFS(cachedvfs.From(osvfs.FS()))
64
+ host := shimcompiler.NewCompilerHost(cwd, fs, bundled.LibPath(), nil, nil)
65
65
 
66
- parsed, parseDiags := tsoptions.GetParsedCommandLineOfConfigFile(
67
- resolved,
68
- &shimcore.CompilerOptions{},
69
- nil,
70
- host,
71
- nil,
72
- )
73
- if parsed == nil {
74
- return nil, nil, fmt.Errorf("tsoptions: parsed command line was nil for %s", resolved)
75
- }
76
- if len(parseDiags) > 0 {
77
- return nil, parseDiags, nil
78
- }
79
- if len(parsed.Errors) > 0 {
80
- return nil, parsed.Errors, nil
81
- }
82
- if options.forceNoEmit {
83
- forceNoEmit(parsed)
84
- }
85
- if options.forceEmit {
86
- forceEmit(parsed)
87
- }
88
- if options.outDir != "" {
89
- overrideOutDir(cwd, parsed, options.outDir)
90
- }
66
+ parsed, parseDiags := tsoptions.GetParsedCommandLineOfConfigFile(
67
+ resolved,
68
+ &shimcore.CompilerOptions{},
69
+ nil,
70
+ host,
71
+ nil,
72
+ )
73
+ if parsed == nil {
74
+ return nil, nil, fmt.Errorf("tsoptions: parsed command line was nil for %s", resolved)
75
+ }
76
+ if len(parseDiags) > 0 {
77
+ return nil, parseDiags, nil
78
+ }
79
+ if len(parsed.Errors) > 0 {
80
+ return nil, parsed.Errors, nil
81
+ }
82
+ if options.forceNoEmit {
83
+ forceNoEmit(parsed)
84
+ }
85
+ if options.forceEmit {
86
+ forceEmit(parsed)
87
+ }
88
+ if options.outDir != "" {
89
+ overrideOutDir(cwd, parsed, options.outDir)
90
+ }
91
91
 
92
- tsProgram := shimcompiler.NewProgram(shimcompiler.ProgramOptions{
93
- Config: parsed,
94
- SingleThreaded: shimcore.TSTrue,
95
- Host: host,
96
- UseSourceOfProjectReference: true,
97
- })
98
- if tsProgram == nil {
99
- return nil, nil, errors.New("compiler.NewProgram returned nil")
100
- }
101
- checker, release := tsProgram.GetTypeChecker(context.Background())
102
- return &program{
103
- cwd: cwd,
104
- tsProgram: tsProgram,
105
- parsed: parsed,
106
- checker: checker,
107
- releaseChecker: release,
108
- }, nil, nil
92
+ tsProgram := shimcompiler.NewProgram(shimcompiler.ProgramOptions{
93
+ Config: parsed,
94
+ SingleThreaded: shimcore.TSTrue,
95
+ Host: host,
96
+ UseSourceOfProjectReference: true,
97
+ })
98
+ if tsProgram == nil {
99
+ return nil, nil, errors.New("compiler.NewProgram returned nil")
100
+ }
101
+ checker, release := tsProgram.GetTypeChecker(context.Background())
102
+ return &program{
103
+ cwd: cwd,
104
+ tsProgram: tsProgram,
105
+ parsed: parsed,
106
+ checker: checker,
107
+ releaseChecker: release,
108
+ }, nil, nil
109
109
  }
110
110
 
111
111
  func (p *program) close() {
112
- if p == nil {
113
- return
114
- }
115
- if p.releaseChecker != nil {
116
- p.releaseChecker()
117
- p.releaseChecker = nil
118
- }
112
+ if p == nil {
113
+ return
114
+ }
115
+ if p.releaseChecker != nil {
116
+ p.releaseChecker()
117
+ p.releaseChecker = nil
118
+ }
119
119
  }
120
120
 
121
121
  // userSourceFiles returns the program's user-authored source files
122
122
  // (declaration files filtered out — those belong to library typings).
123
123
  func (p *program) userSourceFiles() []*shimast.SourceFile {
124
- out := make([]*shimast.SourceFile, 0)
125
- for _, f := range p.tsProgram.SourceFiles() {
126
- if f == nil || f.IsDeclarationFile {
127
- continue
128
- }
129
- out = append(out, f)
130
- }
131
- return out
124
+ out := make([]*shimast.SourceFile, 0)
125
+ for _, f := range p.tsProgram.SourceFiles() {
126
+ if f == nil || f.IsDeclarationFile {
127
+ continue
128
+ }
129
+ out = append(out, f)
130
+ }
131
+ return out
132
132
  }
133
133
 
134
134
  // programDiagnostics returns the bind + semantic diagnostics for the
135
135
  // loaded program. Same surface tsgo's CLI prints when you run a regular
136
136
  // `tsgo --noEmit`.
137
137
  func (p *program) programDiagnostics() []*shimast.Diagnostic {
138
- if p == nil || p.tsProgram == nil {
139
- return nil
140
- }
141
- ctx := context.Background()
142
- raw := shimcompiler.GetDiagnosticsOfAnyProgram(
143
- ctx,
144
- p.tsProgram,
145
- nil,
146
- false,
147
- p.tsProgram.GetBindDiagnostics,
148
- p.tsProgram.GetSemanticDiagnostics,
149
- )
150
- return shimcompiler.SortAndDeduplicateDiagnostics(raw)
138
+ if p == nil || p.tsProgram == nil {
139
+ return nil
140
+ }
141
+ ctx := context.Background()
142
+ raw := shimcompiler.GetDiagnosticsOfAnyProgram(
143
+ ctx,
144
+ p.tsProgram,
145
+ nil,
146
+ false,
147
+ p.tsProgram.GetBindDiagnostics,
148
+ p.tsProgram.GetSemanticDiagnostics,
149
+ )
150
+ return shimcompiler.SortAndDeduplicateDiagnostics(raw)
151
151
  }
152
152
 
153
153
  // findSourceFile locates a source file in the program by absolute path.
154
154
  // tsgo normalizes paths to forward slashes; we do the same on our side.
155
155
  func (p *program) findSourceFile(target string) *shimast.SourceFile {
156
- want := filepath.ToSlash(target)
157
- for _, file := range p.tsProgram.SourceFiles() {
158
- if filepath.ToSlash(file.FileName()) == want {
159
- return file
160
- }
161
- }
162
- return nil
156
+ want := filepath.ToSlash(target)
157
+ for _, file := range p.tsProgram.SourceFiles() {
158
+ if filepath.ToSlash(file.FileName()) == want {
159
+ return file
160
+ }
161
+ }
162
+ return nil
163
163
  }
164
164
 
165
165
  func forceEmit(parsed *tsoptions.ParsedCommandLine) {
166
- if parsed == nil || parsed.ParsedConfig == nil || parsed.ParsedConfig.CompilerOptions == nil {
167
- return
168
- }
169
- options := parsed.ParsedConfig.CompilerOptions
170
- options.NoEmit = shimcore.TSFalse
171
- options.EmitDeclarationOnly = shimcore.TSFalse
166
+ if parsed == nil || parsed.ParsedConfig == nil || parsed.ParsedConfig.CompilerOptions == nil {
167
+ return
168
+ }
169
+ options := parsed.ParsedConfig.CompilerOptions
170
+ options.NoEmit = shimcore.TSFalse
171
+ options.EmitDeclarationOnly = shimcore.TSFalse
172
172
  }
173
173
 
174
174
  func forceNoEmit(parsed *tsoptions.ParsedCommandLine) {
175
- if parsed == nil || parsed.ParsedConfig == nil || parsed.ParsedConfig.CompilerOptions == nil {
176
- return
177
- }
178
- parsed.ParsedConfig.CompilerOptions.NoEmit = shimcore.TSTrue
175
+ if parsed == nil || parsed.ParsedConfig == nil || parsed.ParsedConfig.CompilerOptions == nil {
176
+ return
177
+ }
178
+ parsed.ParsedConfig.CompilerOptions.NoEmit = shimcore.TSTrue
179
179
  }
180
180
 
181
181
  func overrideOutDir(cwd string, parsed *tsoptions.ParsedCommandLine, outDir string) {
182
- if parsed == nil || parsed.ParsedConfig == nil || parsed.ParsedConfig.CompilerOptions == nil {
183
- return
184
- }
185
- if filepath.IsAbs(outDir) {
186
- parsed.ParsedConfig.CompilerOptions.OutDir = filepath.ToSlash(outDir)
187
- return
188
- }
189
- parsed.ParsedConfig.CompilerOptions.OutDir = filepath.ToSlash(filepath.Join(cwd, outDir))
182
+ if parsed == nil || parsed.ParsedConfig == nil || parsed.ParsedConfig.CompilerOptions == nil {
183
+ return
184
+ }
185
+ if filepath.IsAbs(outDir) {
186
+ parsed.ParsedConfig.CompilerOptions.OutDir = filepath.ToSlash(outDir)
187
+ return
188
+ }
189
+ parsed.ParsedConfig.CompilerOptions.OutDir = filepath.ToSlash(filepath.Join(cwd, outDir))
190
190
  }
package/plugin/main.go CHANGED
@@ -16,33 +16,33 @@
16
16
  package main
17
17
 
18
18
  import (
19
- "fmt"
20
- "os"
19
+ "fmt"
20
+ "os"
21
21
  )
22
22
 
23
23
  const version = "0.0.1"
24
24
 
25
25
  func main() {
26
- os.Exit(run(os.Args[1:]))
26
+ os.Exit(run(os.Args[1:]))
27
27
  }
28
28
 
29
29
  func run(args []string) int {
30
- if len(args) == 0 {
31
- fmt.Fprintln(os.Stderr, "@ttsc/lint: command required (expected check|build|transform|version)")
32
- return 2
33
- }
34
- switch args[0] {
35
- case "-v", "--version", "version":
36
- fmt.Fprintf(os.Stdout, "@ttsc/lint %s\n", version)
37
- return 0
38
- case "check":
39
- return RunCheck(args[1:])
40
- case "build":
41
- return RunBuild(args[1:])
42
- case "transform":
43
- return RunTransform(args[1:])
44
- default:
45
- fmt.Fprintf(os.Stderr, "@ttsc/lint: unknown command %q\n", args[0])
46
- return 2
47
- }
30
+ if len(args) == 0 {
31
+ fmt.Fprintln(os.Stderr, "@ttsc/lint: command required (expected check|build|transform|version)")
32
+ return 2
33
+ }
34
+ switch args[0] {
35
+ case "-v", "--version", "version":
36
+ fmt.Fprintf(os.Stdout, "@ttsc/lint %s\n", version)
37
+ return 0
38
+ case "check":
39
+ return RunCheck(args[1:])
40
+ case "build":
41
+ return RunBuild(args[1:])
42
+ case "transform":
43
+ return RunTransform(args[1:])
44
+ default:
45
+ fmt.Fprintf(os.Stderr, "@ttsc/lint: unknown command %q\n", args[0])
46
+ return 2
47
+ }
48
48
  }
@@ -9,19 +9,19 @@ type noSparseArrays struct{}
9
9
 
10
10
  func (noSparseArrays) Name() string { return "no-sparse-arrays" }
11
11
  func (noSparseArrays) Visits() []shimast.Kind {
12
- return []shimast.Kind{shimast.KindArrayLiteralExpression}
12
+ return []shimast.Kind{shimast.KindArrayLiteralExpression}
13
13
  }
14
14
  func (noSparseArrays) Check(ctx *Context, node *shimast.Node) {
15
- arr := node.AsArrayLiteralExpression()
16
- if arr == nil || arr.Elements == nil {
17
- return
18
- }
19
- for _, el := range arr.Elements.Nodes {
20
- if el != nil && el.Kind == shimast.KindOmittedExpression {
21
- ctx.Report(node, "Unexpected comma in middle of array.")
22
- return
23
- }
24
- }
15
+ arr := node.AsArrayLiteralExpression()
16
+ if arr == nil || arr.Elements == nil {
17
+ return
18
+ }
19
+ for _, el := range arr.Elements.Nodes {
20
+ if el != nil && el.Kind == shimast.KindOmittedExpression {
21
+ ctx.Report(node, "Unexpected comma in middle of array.")
22
+ return
23
+ }
24
+ }
25
25
  }
26
26
 
27
27
  // no-array-constructor: forbid `new Array(0)` / `Array(1, 2, 3)` (use
@@ -32,49 +32,49 @@ type noArrayConstructor struct{}
32
32
 
33
33
  func (noArrayConstructor) Name() string { return "no-array-constructor" }
34
34
  func (noArrayConstructor) Visits() []shimast.Kind {
35
- return []shimast.Kind{shimast.KindNewExpression, shimast.KindCallExpression}
35
+ return []shimast.Kind{shimast.KindNewExpression, shimast.KindCallExpression}
36
36
  }
37
37
  func (noArrayConstructor) Check(ctx *Context, node *shimast.Node) {
38
- var callee *shimast.Node
39
- var argCount int
40
- switch node.Kind {
41
- case shimast.KindNewExpression:
42
- ne := node.AsNewExpression()
43
- if ne == nil {
44
- return
45
- }
46
- if ne.TypeArguments != nil && len(ne.TypeArguments.Nodes) > 0 {
47
- return // `new Array<string>()` is a typed empty array
48
- }
49
- callee = ne.Expression
50
- if ne.Arguments != nil {
51
- argCount = len(ne.Arguments.Nodes)
52
- }
53
- case shimast.KindCallExpression:
54
- call := node.AsCallExpression()
55
- if call == nil {
56
- return
57
- }
58
- if call.TypeArguments != nil && len(call.TypeArguments.Nodes) > 0 {
59
- return
60
- }
61
- callee = call.Expression
62
- if call.Arguments != nil {
63
- argCount = len(call.Arguments.Nodes)
64
- }
65
- }
66
- if identifierText(callee) != "Array" {
67
- return
68
- }
69
- // Single-arg numeric — ambiguous (length vs single element). Skip
70
- // so existing patterns aren't flagged when the intent is preallocate.
71
- if argCount == 1 {
72
- return
73
- }
74
- ctx.Report(node, "The array literal notation [] is preferable.")
38
+ var callee *shimast.Node
39
+ var argCount int
40
+ switch node.Kind {
41
+ case shimast.KindNewExpression:
42
+ ne := node.AsNewExpression()
43
+ if ne == nil {
44
+ return
45
+ }
46
+ if ne.TypeArguments != nil && len(ne.TypeArguments.Nodes) > 0 {
47
+ return // `new Array<string>()` is a typed empty array
48
+ }
49
+ callee = ne.Expression
50
+ if ne.Arguments != nil {
51
+ argCount = len(ne.Arguments.Nodes)
52
+ }
53
+ case shimast.KindCallExpression:
54
+ call := node.AsCallExpression()
55
+ if call == nil {
56
+ return
57
+ }
58
+ if call.TypeArguments != nil && len(call.TypeArguments.Nodes) > 0 {
59
+ return
60
+ }
61
+ callee = call.Expression
62
+ if call.Arguments != nil {
63
+ argCount = len(call.Arguments.Nodes)
64
+ }
65
+ }
66
+ if identifierText(callee) != "Array" {
67
+ return
68
+ }
69
+ // Single-arg numeric — ambiguous (length vs single element). Skip
70
+ // so existing patterns aren't flagged when the intent is preallocate.
71
+ if argCount == 1 {
72
+ return
73
+ }
74
+ ctx.Report(node, "The array literal notation [] is preferable.")
75
75
  }
76
76
 
77
77
  func init() {
78
- Register(noSparseArrays{})
79
- Register(noArrayConstructor{})
78
+ Register(noSparseArrays{})
79
+ Register(noArrayConstructor{})
80
80
  }
@@ -2,36 +2,35 @@ package main
2
2
 
3
3
  import shimast "github.com/microsoft/typescript-go/shim/ast"
4
4
 
5
- // no-console: forbid `console.*` calls. Default mode flags every method;
6
- // users who want to allow specific methods can configure ESLint-style
7
- // allowlists in a future iteration.
5
+ // no-console: forbid `console.*` calls. This implementation models the
6
+ // default rule shape and flags every console method.
8
7
  // https://eslint.org/docs/latest/rules/no-console
9
8
  type noConsole struct{}
10
9
 
11
10
  func (noConsole) Name() string { return "no-console" }
12
11
  func (noConsole) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindCallExpression} }
13
12
  func (noConsole) Check(ctx *Context, node *shimast.Node) {
14
- call := node.AsCallExpression()
15
- if call == nil || call.Expression == nil {
16
- return
17
- }
18
- if call.Expression.Kind != shimast.KindPropertyAccessExpression {
19
- return
20
- }
21
- access := call.Expression.AsPropertyAccessExpression()
22
- if access == nil {
23
- return
24
- }
25
- if identifierText(access.Expression) != "console" {
26
- return
27
- }
28
- method := identifierText(access.Name())
29
- if method == "" {
30
- return
31
- }
32
- ctx.Report(node, "Unexpected console statement.")
13
+ call := node.AsCallExpression()
14
+ if call == nil || call.Expression == nil {
15
+ return
16
+ }
17
+ if call.Expression.Kind != shimast.KindPropertyAccessExpression {
18
+ return
19
+ }
20
+ access := call.Expression.AsPropertyAccessExpression()
21
+ if access == nil {
22
+ return
23
+ }
24
+ if identifierText(access.Expression) != "console" {
25
+ return
26
+ }
27
+ method := identifierText(access.Name())
28
+ if method == "" {
29
+ return
30
+ }
31
+ ctx.Report(node, "Unexpected console statement.")
33
32
  }
34
33
 
35
34
  func init() {
36
- Register(noConsole{})
35
+ Register(noConsole{})
37
36
  }
@@ -9,7 +9,7 @@ type noDebugger struct{}
9
9
  func (noDebugger) Name() string { return "no-debugger" }
10
10
  func (noDebugger) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindDebuggerStatement} }
11
11
  func (noDebugger) Check(ctx *Context, node *shimast.Node) {
12
- ctx.Report(node, "Unexpected `debugger` statement.")
12
+ ctx.Report(node, "Unexpected `debugger` statement.")
13
13
  }
14
14
 
15
15
  // no-with: forbid `with` statements (already disallowed in strict mode,
@@ -20,10 +20,10 @@ type noWith struct{}
20
20
  func (noWith) Name() string { return "no-with" }
21
21
  func (noWith) Visits() []shimast.Kind { return []shimast.Kind{shimast.KindWithStatement} }
22
22
  func (noWith) Check(ctx *Context, node *shimast.Node) {
23
- ctx.Report(node, "Unexpected `with` statement.")
23
+ ctx.Report(node, "Unexpected `with` statement.")
24
24
  }
25
25
 
26
26
  func init() {
27
- Register(noDebugger{})
28
- Register(noWith{})
27
+ Register(noDebugger{})
28
+ Register(noWith{})
29
29
  }