Skip to content

Enable error baselines #425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Mar 10, 2025
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ dist

# Test binary, built with `go test -c`
*.test
__debug_bin*

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
Expand Down
9 changes: 9 additions & 0 deletions internal/checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"unicode/utf8"

"github.com/microsoft/typescript-go/internal/ast"
Expand Down Expand Up @@ -518,7 +519,10 @@ type Host interface{}

// Checker

var nextCheckerID atomic.Uint32

type Checker struct {
id uint32
program Program
host Host
compilerOptions *core.CompilerOptions
Expand Down Expand Up @@ -803,6 +807,7 @@ type Checker struct {

func NewChecker(program Program) *Checker {
c := &Checker{}
c.id = nextCheckerID.Add(1)
c.program = program
// c.host = program.host
c.compilerOptions = program.Options()
Expand Down Expand Up @@ -12955,6 +12960,10 @@ func (c *Checker) GetDiagnostics(sourceFile *ast.SourceFile) []*ast.Diagnostic {
return c.diagnostics.GetDiagnostics()
}

func (c *Checker) GetDiagnosticsWithoutCheck(sourceFile *ast.SourceFile) []*ast.Diagnostic {
return c.diagnostics.GetDiagnosticsForFile(sourceFile.FileName())
}

func (c *Checker) GetGlobalDiagnostics() []*ast.Diagnostic {
return c.diagnostics.GetGlobalDiagnostics()
}
Expand Down
16 changes: 15 additions & 1 deletion internal/compiler/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,21 @@ func (p *Program) getBindDiagnosticsForFile(sourceFile *ast.SourceFile) []*ast.D
}

func (p *Program) getSemanticDiagnosticsForFile(sourceFile *ast.SourceFile) []*ast.Diagnostic {
diags := core.Concatenate(sourceFile.BindDiagnostics(), p.GetTypeCheckerForFile(sourceFile).GetDiagnostics(sourceFile))
var fileChecker *checker.Checker
if sourceFile != nil {
fileChecker = p.GetTypeCheckerForFile(sourceFile)
}

diags := slices.Clip(sourceFile.BindDiagnostics())
// Ask for diags from all checkers; checking one file may add diagnostics to other files.
// These are deduplicated later.
for _, checker := range p.checkers {
if sourceFile == nil || checker == fileChecker {
diags = append(diags, checker.GetDiagnostics(sourceFile)...)
} else {
diags = append(diags, checker.GetDiagnosticsWithoutCheck(sourceFile)...)
}
}
if len(sourceFile.CommentDirectives) == 0 {
return diags
}
Expand Down
2 changes: 1 addition & 1 deletion internal/testutil/baseline/baseline.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func getBaselineDiff(t *testing.T, actual string, fileName string) string {
}
var b strings.Builder
if err := diff.Text("old."+fileName, "new."+fileName, expected, actual, &b); err != nil {
t.Fatalf("failed to diff the actual and expected content: %v", err)
return fmt.Sprintf("failed to diff the actual and expected content: %v\n", err)
}

// Remove line numbers from unified diff headers; this avoids adding/deleting
Expand Down
31 changes: 22 additions & 9 deletions internal/testutil/runner/compiler_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,19 +159,19 @@ func (r *CompilerBaselineRunner) runTest(t *testing.T, filename string) {
if config.Name != "" {
testName += " " + config.Name
}
t.Run(testName, func(t *testing.T) { r.runSingleConfigTest(t, test, config) })
t.Run(testName, func(t *testing.T) { r.runSingleConfigTest(t, testName, test, config) })
}
} else {
t.Run(basename, func(t *testing.T) { r.runSingleConfigTest(t, test, nil) })
t.Run(basename, func(t *testing.T) { r.runSingleConfigTest(t, basename, test, nil) })
}
}

func (r *CompilerBaselineRunner) runSingleConfigTest(t *testing.T, test *compilerFileBasedTest, config *harnessutil.NamedTestConfiguration) {
func (r *CompilerBaselineRunner) runSingleConfigTest(t *testing.T, testName string, test *compilerFileBasedTest, config *harnessutil.NamedTestConfiguration) {
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on compiling test "+test.filename)

payload := makeUnitsFromTest(test.content, test.filename)
compilerTest := newCompilerTest(t, test.filename, &payload, config)
compilerTest := newCompilerTest(t, testName, test.filename, &payload, config)

compilerTest.verifyDiagnostics(t, r.testSuitName, r.isSubmodule)
compilerTest.verifyTypesAndSymbols(t, r.testSuitName, r.isSubmodule)
Expand Down Expand Up @@ -199,6 +199,7 @@ func getCompilerFileBasedTest(t *testing.T, filename string) *compilerFileBasedT
}

type compilerTest struct {
testName string
filename string
basename string
configuredName string // name with configuration description, e.g. `file`
Expand All @@ -218,6 +219,7 @@ type testCaseContentWithConfig struct {

func newCompilerTest(
t *testing.T,
testName string,
filename string,
testContent *testCaseContent,
namedConfiguration *harnessutil.NamedTestConfiguration,
Expand Down Expand Up @@ -302,6 +304,7 @@ func newCompilerTest(
)

return &compilerTest{
testName: testName,
filename: filename,
basename: basename,
configuredName: configuredName,
Expand All @@ -315,13 +318,23 @@ func newCompilerTest(
}
}

func (c *compilerTest) verifyDiagnostics(t *testing.T, suiteName string, isSubmodule bool) {
if isSubmodule {
// !!! Enable this when we're ready to diff test diagnostics
return
}
var concurrentSkippedErrorBaselines = core.NewSetFromItems(
"circular1.ts",
"circular3.ts",
"recursiveExportAssignmentAndFindAliasedType1.ts",
"recursiveExportAssignmentAndFindAliasedType2.ts",
"recursiveExportAssignmentAndFindAliasedType3.ts",
"superInStaticMembers1.ts target=es2015",
"typeOnlyMerge2.ts",
"typeOnlyMerge3.ts",
)

func (c *compilerTest) verifyDiagnostics(t *testing.T, suiteName string, isSubmodule bool) {
t.Run("error", func(t *testing.T) {
if !testutil.TestProgramIsSingleThreaded() && concurrentSkippedErrorBaselines.Has(c.testName) {
t.Skip("Skipping error baseline in concurrent mode")
}

defer testutil.RecoverAndFail(t, "Panic on creating error baseline for test "+c.filename)
files := core.Concatenate(c.tsConfigFiles, core.Concatenate(c.toBeCompiled, c.otherFiles))
tsbaseline.DoErrorBaseline(t, c.configuredName, files, c.result.Diagnostics, c.result.Options.Pretty.IsTrue(), baseline.Options{Subfolder: suiteName, IsSubmodule: isSubmodule})
Expand Down
14 changes: 10 additions & 4 deletions internal/testutil/tsbaseline/error_baseline.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ func iterateErrorBaseline(t *testing.T, inputFiles []*harnessutil.TestFile, inpu
lines := lineDelimiter.Split(inputFile.Content, -1)

for lineIndex, line := range lines {
if len(line) > 0 && line[len(line)-1] == '\r' {
line = line[:len(line)-1]
}

thisLineStart := int(lineStarts[lineIndex])
var nextLineStart int
// On the last line of the file, fake the next line start number so that we handle errors on the last character of the file correctly
Expand All @@ -189,19 +193,21 @@ func iterateErrorBaseline(t *testing.T, inputFiles []*harnessutil.TestFile, inpu
outputLines.WriteString(line)
for _, errDiagnostic := range fileErrors {
// Does any error start or continue on to this line? Emit squiggles
errStart := errDiagnostic.Loc().Pos()
end := errDiagnostic.Loc().End()
if end >= thisLineStart && (errDiagnostic.Loc().Pos() < nextLineStart || lineIndex == len(lines)-1) {
if end >= thisLineStart && (errStart < nextLineStart || lineIndex == len(lines)-1) {
// How many characters from the start of this line the error starts at (could be positive or negative)
relativeOffset := errDiagnostic.Loc().Pos() - thisLineStart
relativeOffset := errStart - thisLineStart
// How many characters of the error are on this line (might be longer than this line in reality)
length := (end - errDiagnostic.Loc().Pos()) - max(0, -relativeOffset)
length := (end - errStart) - max(0, thisLineStart-errStart)
// Calculate the start of the squiggle
squiggleStart := max(0, relativeOffset)
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
outputLines.WriteString(newLine())
outputLines.WriteString(" ")
outputLines.WriteString(nonWhitespace.ReplaceAllString(line[:squiggleStart], " "))
outputLines.WriteString(strings.Repeat("~", min(length, len(line)-squiggleStart)))
// This was `new Array(count).join("~")`; which maps 0 to "", 1 to "", 2 to "~", 3 to "~~", etc.
outputLines.WriteString(strings.Repeat("~", max(0, min(length, len(line)-squiggleStart))))

// If the error ended here, or we're at the end of the file, emit its message
if lineIndex == len(lines)-1 || nextLineStart > end {
Expand Down
2 changes: 2 additions & 0 deletions internal/testutil/tsbaseline/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var (
"/.ts/", "",
"/.lib/", "",
"/.src/", "",
"bundled:///libs/", "",
"file:///./ts/", "file:///",
"file:///./lib/", "file:///",
"file:///./src/", "file:///",
Expand All @@ -33,6 +34,7 @@ var (
"/.ts/", "/",
"/.lib/", "/",
"/.src/", "/",
"bundled:///libs/", "/",
"file:///./ts/", "file:///",
"file:///./lib/", "file:///",
"file:///./src/", "file:///",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
index.ts(1,21): error TS2307: Cannot find module 'typescript' or its corresponding type declarations.
index.ts(2,29): error TS2307: Cannot find module 'typescript-internal' or its corresponding type declarations.
index.ts(3,34): error TS2307: Cannot find module 'tsserverlibrary' or its corresponding type declarations.
index.ts(4,42): error TS2307: Cannot find module 'tsserverlibrary-internal' or its corresponding type declarations.


==== index.ts (4 errors) ====
import ts = require("typescript");
~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'typescript' or its corresponding type declarations.
import tsInternal = require("typescript-internal");
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'typescript-internal' or its corresponding type declarations.
import tsserverlibrary = require("tsserverlibrary");
~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'tsserverlibrary' or its corresponding type declarations.
import tsserverlibraryInternal = require("tsserverlibrary-internal");
~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2307: Cannot find module 'tsserverlibrary-internal' or its corresponding type declarations.

==== node_modules/typescript/package.json (0 errors) ====
{
"name": "typescript",
"types": "/.ts/typescript.d.ts"
}

==== node_modules/typescript-internal/package.json (0 errors) ====
{
"name": "typescript-internal",
"types": "/.ts/typescript.internal.d.ts"
}

==== node_modules/tsserverlibrary/package.json (0 errors) ====
{
"name": "tsserverlibrary",
"types": "/.ts/tsserverlibrary.d.ts"
}

==== node_modules/tsserverlibrary-internal/package.json (0 errors) ====
{
"name": "tsserverlibrary-internal",
"types": "/.ts/tsserverlibrary.internal.d.ts"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
--- old.APILibCheck.errors.txt
+++ new.APILibCheck.errors.txt
@@= skipped -0, +-1 lines =@@
-<no content>
@@= skipped --1, +1 lines =@@
+index.ts(1,21): error TS2307: Cannot find module 'typescript' or its corresponding type declarations.
+index.ts(2,29): error TS2307: Cannot find module 'typescript-internal' or its corresponding type declarations.
+index.ts(3,34): error TS2307: Cannot find module 'tsserverlibrary' or its corresponding type declarations.
+index.ts(4,42): error TS2307: Cannot find module 'tsserverlibrary-internal' or its corresponding type declarations.
+
+
+==== index.ts (4 errors) ====
+ import ts = require("typescript");
+ ~~~~~~~~~~~~
+!!! error TS2307: Cannot find module 'typescript' or its corresponding type declarations.
+ import tsInternal = require("typescript-internal");
+ ~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2307: Cannot find module 'typescript-internal' or its corresponding type declarations.
+ import tsserverlibrary = require("tsserverlibrary");
+ ~~~~~~~~~~~~~~~~~
+!!! error TS2307: Cannot find module 'tsserverlibrary' or its corresponding type declarations.
+ import tsserverlibraryInternal = require("tsserverlibrary-internal");
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2307: Cannot find module 'tsserverlibrary-internal' or its corresponding type declarations.
+
+==== node_modules/typescript/package.json (0 errors) ====
+ {
+ "name": "typescript",
+ "types": "/.ts/typescript.d.ts"
+ }
+
+==== node_modules/typescript-internal/package.json (0 errors) ====
+ {
+ "name": "typescript-internal",
+ "types": "/.ts/typescript.internal.d.ts"
+ }
+
+==== node_modules/tsserverlibrary/package.json (0 errors) ====
+ {
+ "name": "tsserverlibrary",
+ "types": "/.ts/tsserverlibrary.d.ts"
+ }
+
+==== node_modules/tsserverlibrary-internal/package.json (0 errors) ====
+ {
+ "name": "tsserverlibrary-internal",
+ "types": "/.ts/tsserverlibrary.internal.d.ts"
+ }
+
Loading