ttsc 0.9.0 → 0.10.1

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.
@@ -7,24 +7,25 @@
7
7
  package main
8
8
 
9
9
  import (
10
- "encoding/json"
11
- "flag"
12
- "fmt"
13
- "os"
14
- "path/filepath"
15
- "strings"
10
+ "encoding/json"
11
+ "flag"
12
+ "fmt"
13
+ "os"
14
+ "path/filepath"
15
+ "strings"
16
16
 
17
- shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
17
+ shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
18
18
 
19
- "github.com/samchon/ttsc/packages/ttsc/driver"
19
+ "github.com/samchon/ttsc/packages/ttsc/driver"
20
+ cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
20
21
  )
21
22
 
22
23
  type apiCompileResult struct {
23
- // Diagnostics is omitted only when the compiler produced no diagnostics.
24
- // Output is still returned in diagnostic cases because TypeScript-Go may
25
- // produce partial emit text before a build-failing error is reported.
26
- Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
27
- Output map[string]string `json:"output"`
24
+ // Diagnostics is omitted only when the compiler produced no diagnostics.
25
+ // Output is still returned in diagnostic cases because TypeScript-Go may
26
+ // produce partial emit text before a build-failing error is reported.
27
+ Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
28
+ Output map[string]string `json:"output"`
28
29
  }
29
30
 
30
31
  // apiCompileDiagnostic mirrors the public TypeScript-side diagnostic DTO.
@@ -32,124 +33,113 @@ type apiCompileResult struct {
32
33
  // `character`) instead of Go naming so callers can pass the data through
33
34
  // without remapping.
34
35
  type apiCompileDiagnostic struct {
35
- File *string `json:"file"`
36
- Category string `json:"category"`
37
- Code int32 `json:"code"`
38
- Start *int `json:"start,omitempty"`
39
- Length *int `json:"length,omitempty"`
40
- Line int `json:"line,omitempty"`
41
- Character int `json:"character,omitempty"`
42
- MessageText string `json:"messageText"`
36
+ File *string `json:"file"`
37
+ Category string `json:"category"`
38
+ Code int32 `json:"code"`
39
+ Start *int `json:"start,omitempty"`
40
+ Length *int `json:"length,omitempty"`
41
+ Line int `json:"line,omitempty"`
42
+ Character int `json:"character,omitempty"`
43
+ MessageText string `json:"messageText"`
43
44
  }
44
45
 
45
46
  func runAPICompile(args []string) int {
46
- fs := flag.NewFlagSet("api-compile", flag.ContinueOnError)
47
- fs.SetOutput(stderr)
48
- tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
49
- cwdOverride := fs.String("cwd", "", "override the working directory")
50
- if err := fs.Parse(args); err != nil {
51
- return 2
52
- }
47
+ fs := flag.NewFlagSet("api-compile", flag.ContinueOnError)
48
+ fs.SetOutput(stderr)
49
+ tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
50
+ cwdOverride := fs.String("cwd", "", "override the working directory")
51
+ if err := fs.Parse(args); err != nil {
52
+ return 2
53
+ }
53
54
 
54
- cwd, ok := resolveBuildCwd(*cwdOverride)
55
- if !ok {
56
- return 2
57
- }
55
+ cwd, err := cwdutil.Resolve(*cwdOverride, os.Getwd)
56
+ if err != nil {
57
+ fmt.Fprintf(stderr, "ttsc: %v\n", err)
58
+ return 2
59
+ }
58
60
 
59
- prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
60
- ForceEmit: true,
61
- })
62
- if err != nil {
63
- fmt.Fprintf(stderr, "ttsc api-compile: %v\n", err)
64
- return 2
65
- }
66
- if prog != nil {
67
- defer prog.Close()
68
- diags = append(diags, prog.Diagnostics()...)
69
- }
61
+ prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
62
+ ForceEmit: true,
63
+ })
64
+ if err != nil {
65
+ fmt.Fprintf(stderr, "ttsc api-compile: %v\n", err)
66
+ return 2
67
+ }
68
+ if prog != nil {
69
+ defer prog.Close()
70
+ diags = append(diags, prog.Diagnostics()...)
71
+ }
70
72
 
71
- output := map[string]string{}
72
- if prog != nil {
73
- rewrites := driver.NewRewriteSet()
74
- // Capture WriteFile output in a map keyed by project-relative paths. This
75
- // gives the JS API a deterministic object and avoids touching outDir.
76
- writeFile := shimcompiler.WriteFile(
77
- func(fileName, text string, _ *shimcompiler.WriteFileData) error {
78
- output[apiOutputKey(cwd, fileName)] = text
79
- return nil
80
- },
81
- )
82
- _, emitDiags, err := prog.EmitAll(rewrites, writeFile)
83
- if err != nil {
84
- fmt.Fprintf(stderr, "ttsc api-compile: emit failed: %v\n", err)
85
- return 3
86
- }
87
- diags = append(diags, emitDiags...)
88
- }
73
+ output := map[string]string{}
74
+ if prog != nil {
75
+ rewrites := driver.NewRewriteSet()
76
+ // Capture WriteFile output in a map keyed by project-relative paths. This
77
+ // gives the JS API a deterministic object and avoids touching outDir.
78
+ writeFile := shimcompiler.WriteFile(
79
+ func(fileName, text string, _ *shimcompiler.WriteFileData) error {
80
+ output[apiOutputKey(cwd, fileName)] = text
81
+ return nil
82
+ },
83
+ )
84
+ _, emitDiags, err := prog.EmitAll(rewrites, writeFile)
85
+ if err != nil {
86
+ fmt.Fprintf(stderr, "ttsc api-compile: emit failed: %v\n", err)
87
+ return 3
88
+ }
89
+ diags = append(diags, emitDiags...)
90
+ }
89
91
 
90
- result := apiCompileResult{
91
- Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
92
- Output: output,
93
- }
94
- for _, diag := range diags {
95
- result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
96
- }
92
+ result := apiCompileResult{
93
+ Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
94
+ Output: output,
95
+ }
96
+ for _, diag := range diags {
97
+ result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
98
+ }
97
99
 
98
- data, err := json.Marshal(result)
99
- if err != nil {
100
- fmt.Fprintf(stderr, "ttsc api-compile: result marshal failed: %v\n", err)
101
- return 3
102
- }
103
- fmt.Fprintln(stdout, string(data))
104
- if driver.CountErrors(diags) > 0 {
105
- return 2
106
- }
107
- return 0
108
- }
109
-
110
- func resolveBuildCwd(cwdOverride string) (string, bool) {
111
- if cwdOverride != "" {
112
- return cwdOverride, true
113
- }
114
- cwd, err := os.Getwd()
115
- if err != nil {
116
- fmt.Fprintf(stderr, "ttsc: could not get working directory: %v\n", err)
117
- return "", false
118
- }
119
- return cwd, true
100
+ data, err := json.Marshal(result)
101
+ if err != nil {
102
+ fmt.Fprintf(stderr, "ttsc api-compile: result marshal failed: %v\n", err)
103
+ return 3
104
+ }
105
+ fmt.Fprintln(stdout, string(data))
106
+ if driver.CountErrors(diags) > 0 {
107
+ return 2
108
+ }
109
+ return 0
120
110
  }
121
111
 
122
112
  func toAPICompileDiagnostic(diag driver.Diagnostic) apiCompileDiagnostic {
123
- var file *string
124
- if diag.File != "" {
125
- value := diag.File
126
- file = &value
127
- }
128
- category := "error"
129
- if diag.Severity == driver.SeverityWarning {
130
- category = "warning"
131
- }
132
- return apiCompileDiagnostic{
133
- File: file,
134
- Category: category,
135
- Code: diag.Code,
136
- Start: diag.Start,
137
- Length: diag.Length,
138
- Line: diag.Line,
139
- Character: diag.Column,
140
- MessageText: diag.Message,
141
- }
113
+ var file *string
114
+ if diag.File != "" {
115
+ value := diag.File
116
+ file = &value
117
+ }
118
+ category := "error"
119
+ if diag.Severity == driver.SeverityWarning {
120
+ category = "warning"
121
+ }
122
+ return apiCompileDiagnostic{
123
+ File: file,
124
+ Category: category,
125
+ Code: diag.Code,
126
+ Start: diag.Start,
127
+ Length: diag.Length,
128
+ Line: diag.Line,
129
+ Character: diag.Column,
130
+ MessageText: diag.Message,
131
+ }
142
132
  }
143
133
 
144
134
  func apiOutputKey(cwd, fileName string) string {
145
- // Relative keys are the API contract for files inside the project. Absolute
146
- // keys are preserved for uncommon compiler outputs outside cwd.
147
- if rel, err := filepath.Rel(cwd, fileName); err == nil && !isOutsideRelativePath(rel) {
148
- return filepath.ToSlash(rel)
149
- }
150
- return filepath.ToSlash(fileName)
135
+ // Relative keys are the API contract for files inside the project. Absolute
136
+ // keys are preserved for uncommon compiler outputs outside cwd.
137
+ if rel, err := filepath.Rel(cwd, fileName); err == nil && !isOutsideRelativePath(rel) {
138
+ return filepath.ToSlash(rel)
139
+ }
140
+ return filepath.ToSlash(fileName)
151
141
  }
152
142
 
153
143
  func isOutsideRelativePath(rel string) bool {
154
- return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
144
+ return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
155
145
  }
@@ -7,66 +7,69 @@
7
7
  package main
8
8
 
9
9
  import (
10
- "encoding/json"
11
- "flag"
12
- "fmt"
10
+ "encoding/json"
11
+ "flag"
12
+ "fmt"
13
+ "os"
13
14
 
14
- "github.com/samchon/ttsc/packages/ttsc/driver"
15
+ "github.com/samchon/ttsc/packages/ttsc/driver"
16
+ cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
15
17
  )
16
18
 
17
19
  type apiTransformResult struct {
18
- // TypeScript contains every non-library source file visible through the
19
- // Program facade, keyed the same way api-compile keys emitted files.
20
- Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
21
- TypeScript map[string]string `json:"typescript"`
20
+ // TypeScript contains every non-library source file visible through the
21
+ // Program facade, keyed the same way api-compile keys emitted files.
22
+ Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
23
+ TypeScript map[string]string `json:"typescript"`
22
24
  }
23
25
 
24
26
  func runAPITransform(args []string) int {
25
- fs := flag.NewFlagSet("api-transform", flag.ContinueOnError)
26
- fs.SetOutput(stderr)
27
- tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
28
- cwdOverride := fs.String("cwd", "", "override the working directory")
29
- if err := fs.Parse(args); err != nil {
30
- return 2
31
- }
27
+ fs := flag.NewFlagSet("api-transform", flag.ContinueOnError)
28
+ fs.SetOutput(stderr)
29
+ tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
30
+ cwdOverride := fs.String("cwd", "", "override the working directory")
31
+ if err := fs.Parse(args); err != nil {
32
+ return 2
33
+ }
32
34
 
33
- cwd, ok := resolveBuildCwd(*cwdOverride)
34
- if !ok {
35
- return 2
36
- }
35
+ cwd, err := cwdutil.Resolve(*cwdOverride, os.Getwd)
36
+ if err != nil {
37
+ fmt.Fprintf(stderr, "ttsc: %v\n", err)
38
+ return 2
39
+ }
37
40
 
38
- prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
39
- ForceNoEmit: true,
40
- })
41
- if err != nil {
42
- fmt.Fprintf(stderr, "ttsc api-transform: %v\n", err)
43
- return 2
44
- }
45
- typescript := map[string]string{}
46
- if prog != nil {
47
- defer prog.Close()
48
- for _, file := range prog.SourceFiles() {
49
- typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
50
- }
51
- diags = append(diags, prog.Diagnostics()...)
52
- }
41
+ prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
42
+ ForceNoEmit: true,
43
+ })
44
+ if err != nil {
45
+ fmt.Fprintf(stderr, "ttsc api-transform: %v\n", err)
46
+ return 2
47
+ }
48
+ typescript := map[string]string{}
49
+ if prog != nil {
50
+ defer prog.Close()
51
+ for _, file := range prog.SourceFiles() {
52
+ typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
53
+ }
54
+ diags = append(diags, prog.Diagnostics()...)
55
+ }
53
56
 
54
- result := apiTransformResult{
55
- Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
56
- TypeScript: typescript,
57
- }
58
- for _, diag := range diags {
59
- result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
60
- }
57
+ result := apiTransformResult{
58
+ Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
59
+ TypeScript: typescript,
60
+ }
61
+ for _, diag := range diags {
62
+ result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
63
+ }
61
64
 
62
- data, err := json.Marshal(result)
63
- if err != nil {
64
- fmt.Fprintf(stderr, "ttsc api-transform: result marshal failed: %v\n", err)
65
- return 3
66
- }
67
- fmt.Fprintln(stdout, string(data))
68
- if driver.CountErrors(diags) > 0 {
69
- return 2
70
- }
71
- return 0
65
+ data, err := json.Marshal(result)
66
+ if err != nil {
67
+ fmt.Fprintf(stderr, "ttsc api-transform: result marshal failed: %v\n", err)
68
+ return 3
69
+ }
70
+ fmt.Fprintln(stdout, string(data))
71
+ if driver.CountErrors(diags) > 0 {
72
+ return 2
73
+ }
74
+ return 0
72
75
  }
package/cmd/ttsc/main.go CHANGED
@@ -12,121 +12,103 @@
12
12
  package main
13
13
 
14
14
  import (
15
- "flag"
16
- "fmt"
17
- "io"
18
- "os"
19
- "runtime"
20
- "strings"
15
+ "flag"
16
+ "fmt"
17
+ "io"
18
+ "os"
19
+ "runtime"
20
+ "strings"
21
21
  )
22
22
 
23
23
  // These are overridden via `-ldflags "-X main.version=... -X main.commit=..."`
24
24
  // in CI. Sensible defaults keep local `go run ./cmd/ttsc` usable.
25
25
  var (
26
- version = "0.0.0-dev"
27
- commit = "dev"
28
- date = "unknown"
26
+ version = "0.0.0-dev"
27
+ commit = "dev"
28
+ date = "unknown"
29
29
  )
30
30
 
31
31
  // stdout / stderr are package-level to keep the CLI testable.
32
32
  var (
33
- stdout io.Writer = os.Stdout
34
- stderr io.Writer = os.Stderr
33
+ stdout io.Writer = os.Stdout
34
+ stderr io.Writer = os.Stderr
35
35
  )
36
36
 
37
37
  func main() {
38
- os.Exit(run(os.Args[1:]))
38
+ os.Exit(run(os.Args[1:]))
39
39
  }
40
40
 
41
41
  func run(args []string) int {
42
- if len(args) == 0 {
43
- return runBuild(nil)
44
- }
45
-
46
- switch args[0] {
47
- case "-h", "--help", "help":
48
- printHelp(stdout)
49
- return 0
50
- case "-v", "--version", "version":
51
- printVersion(stdout)
52
- return 0
53
- case "demo":
54
- return runDemo(args[1:])
55
- case "build":
56
- return runBuild(args[1:])
57
- case "api-compile":
58
- return runAPICompile(args[1:])
59
- case "api-transform":
60
- return runAPITransform(args[1:])
61
- case "check":
62
- // `ttsc check` runs the analyze pipeline without emitting JS — useful
63
- // in CI and pre-commit checks that only need schema validation.
64
- return runBuild(append([]string{"--noEmit"}, args[1:]...))
65
- case "-p", "--project":
66
- if len(args) < 2 {
67
- fmt.Fprintln(stderr, "ttsc: -p/--project requires a path argument")
68
- return 2
69
- }
70
- return runBuild(append([]string{"--tsconfig=" + args[1]}, args[2:]...))
71
- default:
72
- if isBuildAlias(args[0]) {
73
- return runBuild(args)
74
- }
75
- fmt.Fprintf(stderr, "ttsc: unknown command %q\n", args[0])
76
- fmt.Fprintln(stderr, `ttsc: run "ttsc --help" to see supported commands`)
77
- return 2
78
- }
42
+ if len(args) == 0 {
43
+ return runBuild(nil)
44
+ }
45
+
46
+ switch args[0] {
47
+ case "-h", "--help", "help":
48
+ printHelp(stdout)
49
+ return 0
50
+ case "-v", "--version", "version":
51
+ printVersion(stdout)
52
+ return 0
53
+ case "demo":
54
+ return runDemo(args[1:])
55
+ case "build":
56
+ return runBuild(args[1:])
57
+ case "api-compile":
58
+ return runAPICompile(args[1:])
59
+ case "api-transform":
60
+ return runAPITransform(args[1:])
61
+ case "check":
62
+ // `ttsc check` runs the analyze pipeline without emitting JS — useful
63
+ // in CI and pre-commit checks that only need schema validation.
64
+ return runBuild(append([]string{"--noEmit"}, args[1:]...))
65
+ case "-p", "--project":
66
+ if len(args) < 2 {
67
+ fmt.Fprintln(stderr, "ttsc: -p/--project requires a path argument")
68
+ return 2
69
+ }
70
+ return runBuild(append([]string{"--tsconfig=" + args[1]}, args[2:]...))
71
+ default:
72
+ if isBuildAlias(args[0]) {
73
+ return runBuild(args)
74
+ }
75
+ fmt.Fprintf(stderr, "ttsc: unknown command %q\n", args[0])
76
+ fmt.Fprintln(stderr, `ttsc: run "ttsc --help" to see supported commands`)
77
+ return 2
78
+ }
79
79
  }
80
80
 
81
81
  func isBuildAlias(arg string) bool {
82
- if strings.HasPrefix(arg, "-") {
83
- return true
84
- }
85
- switch {
86
- case strings.HasSuffix(arg, ".json"),
87
- strings.HasSuffix(arg, ".ts"),
88
- strings.HasSuffix(arg, ".tsx"),
89
- strings.HasSuffix(arg, ".mts"),
90
- strings.HasSuffix(arg, ".cts"):
91
- return true
92
- default:
93
- return false
94
- }
95
- }
96
-
97
- // appendUnique appends `extra` to `args` only when it's not already present.
98
- func appendUnique(args []string, extra ...string) []string {
99
- out := append([]string{}, args...)
100
- for _, e := range extra {
101
- seen := false
102
- for _, a := range out {
103
- if a == e {
104
- seen = true
105
- break
106
- }
107
- }
108
- if !seen {
109
- out = append(out, e)
110
- }
111
- }
112
- return out
82
+ if strings.HasPrefix(arg, "-") {
83
+ return true
84
+ }
85
+ switch {
86
+ case strings.HasSuffix(arg, ".json"),
87
+ strings.HasSuffix(arg, ".ts"),
88
+ strings.HasSuffix(arg, ".tsx"),
89
+ strings.HasSuffix(arg, ".mts"),
90
+ strings.HasSuffix(arg, ".cts"):
91
+ return true
92
+ default:
93
+ return false
94
+ }
113
95
  }
114
96
 
115
97
  func printVersion(w io.Writer) {
116
- fmt.Fprintf(
117
- w,
118
- "ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
119
- version,
120
- commit,
121
- date,
122
- runtime.GOOS,
123
- runtime.GOARCH,
124
- runtime.Version(),
125
- )
98
+ fmt.Fprintf(
99
+ w,
100
+ "ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
101
+ version,
102
+ commit,
103
+ date,
104
+ runtime.GOOS,
105
+ runtime.GOARCH,
106
+ runtime.Version(),
107
+ )
126
108
  }
127
109
 
128
110
  func printHelp(w io.Writer) {
129
- fmt.Fprintln(w, strings.TrimSpace(`
111
+ fmt.Fprintln(w, strings.TrimSpace(`
130
112
  ttsc — standalone typescript-go host.
131
113
 
132
114
  Usage:
@@ -172,37 +154,37 @@ Integration guide (bundlers):
172
154
  }
173
155
 
174
156
  func runDemo(args []string) int {
175
- fs := flag.NewFlagSet("demo", flag.ContinueOnError)
176
- fs.SetOutput(stderr)
177
- typ := fs.String("type", "string", "atomic type to simulate")
178
- if err := fs.Parse(args); err != nil {
179
- return 2
180
- }
181
-
182
- arrow, err := demoArrow(*typ)
183
- if err != nil {
184
- fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
185
- return 2
186
- }
187
-
188
- fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
189
- fmt.Fprintln(stdout, arrow)
190
- return 0
157
+ fs := flag.NewFlagSet("demo", flag.ContinueOnError)
158
+ fs.SetOutput(stderr)
159
+ typ := fs.String("type", "string", "atomic type to simulate")
160
+ if err := fs.Parse(args); err != nil {
161
+ return 2
162
+ }
163
+
164
+ arrow, err := demoArrow(*typ)
165
+ if err != nil {
166
+ fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
167
+ return 2
168
+ }
169
+
170
+ fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
171
+ fmt.Fprintln(stdout, arrow)
172
+ return 0
191
173
  }
192
174
 
193
175
  func demoArrow(name string) (string, error) {
194
- switch strings.ToLower(name) {
195
- case "any":
196
- return "(input) => true", nil
197
- case "boolean":
198
- return `(input) => "boolean" === typeof input`, nil
199
- case "number":
200
- return `(input) => "number" === typeof input`, nil
201
- case "bigint":
202
- return `(input) => "bigint" === typeof input`, nil
203
- case "string", "":
204
- return `(input) => "string" === typeof input`, nil
205
- default:
206
- return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
207
- }
176
+ switch strings.ToLower(name) {
177
+ case "any":
178
+ return "(input) => true", nil
179
+ case "boolean":
180
+ return `(input) => "boolean" === typeof input`, nil
181
+ case "number":
182
+ return `(input) => "number" === typeof input`, nil
183
+ case "bigint":
184
+ return `(input) => "bigint" === typeof input`, nil
185
+ case "string", "":
186
+ return `(input) => "string" === typeof input`, nil
187
+ default:
188
+ return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
189
+ }
208
190
  }
package/driver/program.go CHANGED
@@ -85,7 +85,7 @@ func NewLintDiagnostic(
85
85
  if file != nil {
86
86
  d.File = file.FileName()
87
87
  if pos >= 0 {
88
- length := end - pos
88
+ length := lint.Len()
89
89
  d.Start = &pos
90
90
  d.Length = &length
91
91
  line, col := shimscanner.GetECMALineAndByteOffsetOfPosition(file, pos)
@@ -240,6 +240,9 @@ func ParseTSConfig(fs vfs.FS, cwd, tsconfigPath string, host shimcompiler.Compil
240
240
 
241
241
  // CreateProgramFromConfig builds a tsgo Program from the parsed config.
242
242
  func CreateProgramFromConfig(parsed *tsoptions.ParsedCommandLine, host shimcompiler.CompilerHost) (*shimcompiler.Program, []Diagnostic, error) {
243
+ if parsed == nil {
244
+ return nil, nil, errors.New("driver: nil parsed command line")
245
+ }
243
246
  opts := shimcompiler.ProgramOptions{
244
247
  Config: parsed,
245
248
  SingleThreaded: core.TSTrue,
@@ -403,6 +406,9 @@ func ApplySourcePreamble(text string, preamble string) string {
403
406
  // files filtered out).
404
407
  func (p *Program) SourceFiles() []*ast.SourceFile {
405
408
  out := make([]*ast.SourceFile, 0)
409
+ if p == nil || p.TSProgram == nil {
410
+ return out
411
+ }
406
412
  for _, f := range p.TSProgram.SourceFiles() {
407
413
  if f.IsDeclarationFile {
408
414
  continue