Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
42590bc
stub for watch
sheetalkamat Aug 22, 2025
8e54774
basic test
sheetalkamat Aug 22, 2025
2ae229f
Update status
sheetalkamat Aug 22, 2025
2278dfd
Reuse tasks and build order when we can
sheetalkamat Aug 22, 2025
2d5feee
Cache buildInfo for life time
sheetalkamat Aug 27, 2025
e1a0d55
use writeFile callback to get updates about writing
sheetalkamat Aug 28, 2025
182364b
rename
sheetalkamat Aug 28, 2025
19f5686
Handle mtimes caching
sheetalkamat Aug 28, 2025
6e15d4c
Handle updates to mTimes in test
sheetalkamat Aug 28, 2025
75ab83d
Fix the dts emit time stamp reversal found from test update
sheetalkamat Aug 28, 2025
45d6996
tsc -b -w root tests porting
sheetalkamat Aug 28, 2025
258a27f
Fix issue with noChange retaining input times in cache
sheetalkamat Aug 28, 2025
69fd252
reexport test
sheetalkamat Aug 28, 2025
77cbab1
Fix incorrect resets for errors
sheetalkamat Aug 29, 2025
38554fc
tsc -b -w program updates tests
sheetalkamat Aug 29, 2025
51aafa3
Fix strict value checking
sheetalkamat Aug 29, 2025
e9c4a24
Fix duplicate error reporting
sheetalkamat Aug 29, 2025
f466e1f
Dirty automatically adds to pending update
sheetalkamat Aug 29, 2025
e058f9c
tsc -b -w noEmitOnError tests
sheetalkamat Aug 30, 2025
74e01c9
Fix the timestamp update for buildInfo in nonIncremental mode
sheetalkamat Sep 2, 2025
2198655
Fix unnecessary tsbuildinfo emits when getting cached dts diagnostics
sheetalkamat Sep 2, 2025
c812ed4
tsc -b -w noEmit testcases
sheetalkamat Sep 2, 2025
8ca329d
Fix incorrectly storing timestamps of file where input and output nam…
sheetalkamat Sep 2, 2025
3284900
tsc -b -w module resolution tests
sheetalkamat Sep 4, 2025
25032de
Fix incorrect reporting of symlink delete
sheetalkamat Sep 4, 2025
efb53b3
tsc -b -w libResolution tests
sheetalkamat Sep 4, 2025
fafb8d5
tsc -b -w extends test case
sheetalkamat Sep 4, 2025
9a1b6ce
config file errors porting
sheetalkamat Sep 4, 2025
334b380
Fix race in source file caching
sheetalkamat Sep 5, 2025
ea637ee
Fix race in creating build task
sheetalkamat Sep 5, 2025
983a1c8
Merge branch 'main' into watchMode
sheetalkamat Sep 8, 2025
b4d1165
Add starting and waiting for changes status
sheetalkamat Sep 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 8 additions & 15 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -875,14 +875,14 @@ func NewChecker(program Program) *Checker {
c.legacyDecorators = c.compilerOptions.ExperimentalDecorators == core.TSTrue
c.emitStandardClassFields = !c.compilerOptions.UseDefineForClassFields.IsFalse() && c.compilerOptions.GetEmitScriptTarget() >= core.ScriptTargetES2022
c.allowSyntheticDefaultImports = c.compilerOptions.GetAllowSyntheticDefaultImports()
c.strictNullChecks = c.getStrictOptionValue(c.compilerOptions.StrictNullChecks)
c.strictFunctionTypes = c.getStrictOptionValue(c.compilerOptions.StrictFunctionTypes)
c.strictBindCallApply = c.getStrictOptionValue(c.compilerOptions.StrictBindCallApply)
c.strictPropertyInitialization = c.getStrictOptionValue(c.compilerOptions.StrictPropertyInitialization)
c.strictBuiltinIteratorReturn = c.getStrictOptionValue(c.compilerOptions.StrictBuiltinIteratorReturn)
c.noImplicitAny = c.getStrictOptionValue(c.compilerOptions.NoImplicitAny)
c.noImplicitThis = c.getStrictOptionValue(c.compilerOptions.NoImplicitThis)
c.useUnknownInCatchVariables = c.getStrictOptionValue(c.compilerOptions.UseUnknownInCatchVariables)
c.strictNullChecks = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.StrictNullChecks)
c.strictFunctionTypes = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.StrictFunctionTypes)
c.strictBindCallApply = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.StrictBindCallApply)
c.strictPropertyInitialization = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.StrictPropertyInitialization)
c.strictBuiltinIteratorReturn = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.StrictBuiltinIteratorReturn)
c.noImplicitAny = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.NoImplicitAny)
c.noImplicitThis = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.NoImplicitThis)
c.useUnknownInCatchVariables = c.compilerOptions.GetStrictOptionValue(c.compilerOptions.UseUnknownInCatchVariables)
c.exactOptionalPropertyTypes = c.compilerOptions.ExactOptionalPropertyTypes == core.TSTrue
c.canCollectSymbolAliasAccessibilityData = c.compilerOptions.VerbatimModuleSyntax.IsFalseOrUnknown()
c.arrayVariances = []VarianceFlags{VarianceFlagsCovariant}
Expand Down Expand Up @@ -1106,13 +1106,6 @@ func (c *Checker) reportUnmeasurableWorker(t *Type) *Type {
return t
}

func (c *Checker) getStrictOptionValue(value core.Tristate) bool {
if value != core.TSUnknown {
return value == core.TSTrue
}
return c.compilerOptions.Strict == core.TSTrue
}

// Resolve to the global class or interface by the given name and arity, or emptyObjectType/emptyGenericType otherwise
func (c *Checker) getGlobalTypeResolver(name string, arity int, reportErrors bool) func() *Type {
return core.Memoize(func() *Type {
Expand Down
9 changes: 9 additions & 0 deletions internal/collections/syncmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,12 @@ func (s *SyncMap[K, V]) Keys() iter.Seq[K] {
})
}
}

func (s *SyncMap[K, V]) Clone() *SyncMap[K, V] {
clone := &SyncMap[K, V]{}
s.m.Range(func(key, value any) bool {
clone.m.Store(key, value)
return true
})
return clone
}
25 changes: 13 additions & 12 deletions internal/compiler/emitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func (e *emitter) printSourceFile(jsFilePath string, sourceMapFilePath string, s
// Write the source map
if len(sourceMapFilePath) > 0 {
sourceMap := sourceMapGenerator.String()
err := e.host.WriteFile(sourceMapFilePath, sourceMap, false /*writeByteOrderMark*/)
err := e.writeText(sourceMapFilePath, sourceMap, false /*writeByteOrderMark*/, nil)
if err != nil {
e.emitterDiagnostics.Add(ast.NewCompilerDiagnostic(diagnostics.Could_not_write_file_0_Colon_1, jsFilePath, err.Error()))
} else {
Expand All @@ -275,18 +275,12 @@ func (e *emitter) printSourceFile(jsFilePath string, sourceMapFilePath string, s

// Write the output file
text := e.writer.String()
var err error
var skippedDtsWrite bool
if e.writeFile == nil {
err = e.host.WriteFile(jsFilePath, text, e.host.Options().EmitBOM.IsTrue())
} else {
data := &WriteFileData{
SourceMapUrlPos: sourceMapUrlPos,
Diagnostics: e.emitterDiagnostics.GetDiagnostics(),
}
err = e.writeFile(jsFilePath, text, e.host.Options().EmitBOM.IsTrue(), data)
skippedDtsWrite = data.SkippedDtsWrite
data := &WriteFileData{
SourceMapUrlPos: sourceMapUrlPos,
Diagnostics: e.emitterDiagnostics.GetDiagnostics(),
}
err := e.writeText(jsFilePath, text, options.EmitBOM.IsTrue(), data)
skippedDtsWrite := data.SkippedDtsWrite
if err != nil {
e.emitterDiagnostics.Add(ast.NewCompilerDiagnostic(diagnostics.Could_not_write_file_0_Colon_1, jsFilePath, err.Error()))
} else if !skippedDtsWrite {
Expand All @@ -297,6 +291,13 @@ func (e *emitter) printSourceFile(jsFilePath string, sourceMapFilePath string, s
e.writer.Clear()
}

func (e *emitter) writeText(fileName string, text string, writeByteOrderMark bool, data *WriteFileData) error {
if e.writeFile != nil {
return e.writeFile(fileName, text, writeByteOrderMark, data)
}
return e.host.WriteFile(fileName, text, writeByteOrderMark)
}

func shouldEmitSourceMaps(mapOptions *core.CompilerOptions, sourceFile *ast.SourceFile) bool {
return (mapOptions.SourceMap.IsTrue() || mapOptions.InlineSourceMap.IsTrue()) &&
!tspath.FileExtensionIs(sourceFile.FileName(), tspath.ExtensionJson)
Expand Down
15 changes: 5 additions & 10 deletions internal/compiler/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,13 +542,6 @@ func (p *Program) verifyCompilerOptions() {
}
}

getStrictOptionValue := func(value core.Tristate) bool {
if value != core.TSUnknown {
return value == core.TSTrue
}
return options.Strict == core.TSTrue
}

// Removed in TS7

if options.BaseUrl != "" {
Expand Down Expand Up @@ -586,10 +579,10 @@ func (p *Program) verifyCompilerOptions() {
createRemovedOptionDiagnostic("module", "UMD", "")
}

if options.StrictPropertyInitialization.IsTrue() && !getStrictOptionValue(options.StrictNullChecks) {
if options.StrictPropertyInitialization.IsTrue() && !options.GetStrictOptionValue(options.StrictNullChecks) {
createDiagnosticForOptionName(diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks")
}
if options.ExactOptionalPropertyTypes.IsTrue() && !getStrictOptionValue(options.StrictNullChecks) {
if options.ExactOptionalPropertyTypes.IsTrue() && !options.GetStrictOptionValue(options.StrictNullChecks) {
createDiagnosticForOptionName(diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "exactOptionalPropertyTypes", "strictNullChecks")
}

Expand Down Expand Up @@ -1341,10 +1334,12 @@ type WriteFileData struct {
SkippedDtsWrite bool
}

type WriteFile func(fileName string, text string, writeByteOrderMark bool, data *WriteFileData) error

type EmitOptions struct {
TargetSourceFile *ast.SourceFile // Single file to emit. If `nil`, emits all files
EmitOnly EmitOnly
WriteFile func(fileName string, text string, writeByteOrderMark bool, data *WriteFileData) error
WriteFile WriteFile
}

type EmitResult struct {
Expand Down
7 changes: 7 additions & 0 deletions internal/core/compileroptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@ func (options *CompilerOptions) GetJSXTransformEnabled() bool {
return jsx == JsxEmitReact || jsx == JsxEmitReactJSX || jsx == JsxEmitReactJSXDev
}

func (options *CompilerOptions) GetStrictOptionValue(value Tristate) bool {
if value != TSUnknown {
return value == TSTrue
}
return options.Strict == TSTrue
}

func (options *CompilerOptions) GetEffectiveTypeRoots(currentDirectory string) (result []string, fromConfig bool) {
if options.TypeRoots != nil {
return options.TypeRoots, true
Expand Down
10 changes: 10 additions & 0 deletions internal/core/watchoptions.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package core

import "time"

type WatchOptions struct {
Interval *int `json:"watchInterval"`
FileKind WatchFileKind `json:"watchFile"`
Expand Down Expand Up @@ -41,3 +43,11 @@ const (
PollingKindDynamicPriority PollingKind = 3
PollingKindFixedChunkSize PollingKind = 4
)

func (w *WatchOptions) WatchInterval() time.Duration {
watchInterval := 1000 * time.Millisecond
if w != nil && w.Interval != nil {
watchInterval = time.Duration(*w.Interval) * time.Millisecond
}
return watchInterval
}
2 changes: 2 additions & 0 deletions internal/diagnostics/diagnostics_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/diagnostics/extraDiagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,9 @@
"Failed to update timestamp of file '{0}'.": {
"category": "Message",
"code": 5074
},
"Project '{0}' is out of date because it has errors.": {
"category": "Message",
"code": 6423
}
}
31 changes: 25 additions & 6 deletions internal/diagnosticwriter/diagnosticwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"unicode"

"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/diagnostics"
"github.com/microsoft/typescript-go/internal/scanner"
"github.com/microsoft/typescript-go/internal/tspath"
Expand Down Expand Up @@ -139,7 +140,8 @@ func writeCodeSnippet(writer io.Writer, sourceFile *ast.SourceFile, start int, l
fmt.Fprint(writer, resetEscapeSequence)
fmt.Fprint(writer, gutterSeparator)
fmt.Fprint(writer, squiggleColor)
if i == firstLine {
switch i {
case firstLine:
// If we're on the last line, then limit it to the last character of the last line.
// Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position.
var lastCharForLine int
Expand All @@ -153,10 +155,10 @@ func writeCodeSnippet(writer io.Writer, sourceFile *ast.SourceFile, start int, l
// then squiggle the remainder of the line.
fmt.Fprint(writer, strings.Repeat(" ", firstLineChar))
fmt.Fprint(writer, strings.Repeat("~", lastCharForLine-firstLineChar))
} else if i == lastLine {
case lastLine:
// Squiggle until the final character.
fmt.Fprint(writer, strings.Repeat("~", lastLineChar))
} else {
default:
// Squiggle the entire line.
fmt.Fprint(writer, strings.Repeat("~", len(lineContent)))
}
Expand Down Expand Up @@ -263,13 +265,14 @@ func WriteErrorSummaryText(output io.Writer, allDiagnostics []*ast.Diagnostic, f
message = diagnostics.Found_1_error_in_0.Format(firstFileName)
}
} else {
if numErroringFiles == 0 {
switch numErroringFiles {
case 0:
// No file-specific errors.
message = diagnostics.Found_0_errors.Format(totalErrorCount)
} else if numErroringFiles == 1 {
case 1:
// One file with errors.
message = diagnostics.Found_0_errors_in_the_same_file_starting_at_Colon_1.Format(totalErrorCount, firstFileName)
} else {
default:
// Multiple files with errors.
message = diagnostics.Found_0_errors_in_1_files.Format(totalErrorCount, numErroringFiles)
}
Expand Down Expand Up @@ -397,3 +400,19 @@ func FormatDiagnosticsStatusAndTime(output io.Writer, time string, diag *ast.Dia
fmt.Fprint(output, time, " - ")
WriteFlattenedDiagnosticMessage(output, diag, formatOpts.NewLine)
}

var ScreenStartingCodes = []int32{
diagnostics.Starting_compilation_in_watch_mode.Code(),
diagnostics.File_change_detected_Starting_incremental_compilation.Code(),
}

func TryClearScreen(output io.Writer, diag *ast.Diagnostic, options *core.CompilerOptions) bool {
if !options.PreserveWatchOutput.IsTrue() &&
!options.ExtendedDiagnostics.IsTrue() &&
!options.Diagnostics.IsTrue() &&
slices.Contains(ScreenStartingCodes, diag.Code()) {
fmt.Fprint(output, "\x1B[2J\x1B[3J\x1B[H") // Clear screen and move cursor to home position
return true
}
return false
}
Loading
Loading