Skip to content

Commit 8975489

Browse files
committed
Merge branch 'fix/2674' of https://github.com/a-tarasyuk/typescript-go into fix/2674
2 parents 13dee6b + 8ff7b03 commit 8975489

56 files changed

Lines changed: 1169 additions & 568 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ jobs:
277277
npx hereby test >/dev/null || true
278278
npx hereby baseline-accept || true
279279
npx hereby test || true
280+
npx hereby baseline-accept || true
281+
npx hereby test
280282
281283
- run: git add .
282284
- run: git diff --staged --exit-code --stat
@@ -332,68 +334,10 @@ jobs:
332334

333335
- run: go -C ./_tools run ./cmd/checkmodpaths $PWD
334336

335-
baselines:
336-
runs-on: ubuntu-latest
337-
steps:
338-
- uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
339-
with:
340-
large-packages: false
341-
docker-images: false
342-
swap-storage: false
343-
dotnet: false
344-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
345-
with:
346-
submodules: true
347-
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
348-
- uses: dtolnay/rust-toolchain@fcf085fcb4b4b8f63f96906cd713eb52181b5ea4 # stable
349-
- uses: ./.github/actions/setup-go
350-
351-
- run: npm ci
352-
353-
- name: Remove all baselines
354-
run: rm -rf testdata/baselines/reference
355-
356-
- name: Run tests
357-
run: npx hereby test &> /dev/null || exit 0
358-
359-
- name: Accept baselines
360-
run: |
361-
npx hereby baseline-accept
362-
git add testdata/baselines/reference
363-
364-
- name: Run tests
365-
run: npx hereby test
366-
367-
- name: Check baselines
368-
id: check-baselines
369-
run: |
370-
function print_diff() {
371-
if ! git diff --staged --exit-code --quiet --diff-filter=$1; then
372-
echo "$2:"
373-
git diff --staged --name-only --diff-filter=$1
374-
fi
375-
}
376-
377-
if ! git diff --staged --exit-code --quiet; then
378-
print_diff ACR "Missing baselines"
379-
print_diff MTUXB "Modified baselines"
380-
print_diff D "Unused baselines"
381-
git diff --staged > fix_baselines.patch
382-
exit 1
383-
fi
384-
385-
- name: Upload baseline diff artifact
386-
if: ${{ failure() && steps.check-baselines.conclusion == 'failure' }}
387-
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
388-
with:
389-
name: fix_baselines.patch
390-
path: fix_baselines.patch
391-
392337
required:
393338
runs-on: ubuntu-latest
394339
if: ${{ always() }}
395340
needs:
396-
- baselines
397341
- build
398342
- extension
399343
- format

Herebyfile.mjs

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import { task } from "hereby";
88
import assert from "node:assert";
99
import crypto from "node:crypto";
1010
import fs from "node:fs";
11+
import os from "node:os";
1112
import path from "node:path";
1213
import url from "node:url";
1314
import { parseArgs } from "node:util";
14-
import os from "os";
1515
import pLimit from "p-limit";
1616
import pc from "picocolors";
17+
import tmp from "tmp";
1718
import which from "which";
1819

1920
const __filename = url.fileURLToPath(new URL(import.meta.url));
@@ -302,11 +303,64 @@ const goTestEnv = {
302303
...(process.platform === "win32" ? { GOFLAGS: "-count=1" } : {}),
303304
};
304305

306+
const baselineTrackingEnabled = isTypeScriptSubmoduleCloned() && ![
307+
options.tests,
308+
options.noembed,
309+
options.concurrentTestPrograms,
310+
options.race,
311+
options.dirty,
312+
].some(Boolean);
313+
305314
const goTestSumFlags = [
306315
"--format-hide-empty-pkg",
307316
...(!isCI ? ["--hide-summary", "skipped"] : []),
308317
];
309318

319+
/**
320+
* Collects all baseline files that were used during the test run.
321+
* @param {string} trackingDir
322+
* @returns {Promise<Set<string>>}
323+
*/
324+
async function collectUsedBaselines(trackingDir) {
325+
/** @type {Set<string>} */
326+
const usedBaselines = new Set();
327+
if (!fs.existsSync(trackingDir)) {
328+
return usedBaselines;
329+
}
330+
331+
const trackingFiles = await fs.promises.readdir(trackingDir);
332+
for (const file of trackingFiles) {
333+
const content = await fs.promises.readFile(path.join(trackingDir, file), "utf-8");
334+
for (const line of content.split("\n")) {
335+
const trimmed = line.trim();
336+
if (trimmed) {
337+
usedBaselines.add(trimmed);
338+
}
339+
}
340+
}
341+
return usedBaselines;
342+
}
343+
344+
/**
345+
* Checks for unused baseline files and reports them.
346+
* @param {string} trackingDir
347+
* @returns {Promise<string[]>} List of unused baseline file paths.
348+
*/
349+
async function checkUnusedBaselines(trackingDir) {
350+
const usedBaselines = await collectUsedBaselines(trackingDir);
351+
if (usedBaselines.size === 0) {
352+
// No baselines recorded - either no tests ran or tracking wasn't set up properly
353+
return [];
354+
}
355+
356+
const allBaselines = await glob(`${refBaseline}/**`, { nodir: true });
357+
const unusedBaselines = allBaselines
358+
.map(p => path.relative(refBaseline, p))
359+
.filter(p => !usedBaselines.has(p));
360+
361+
return unusedBaselines;
362+
}
363+
310364
const $test = $({ env: goTestEnv });
311365

312366
/**
@@ -332,7 +386,55 @@ async function runTests() {
332386
await fs.promises.mkdir(localBaseline, { recursive: true });
333387
}
334388

335-
await $test`${gotestsum("tests")} ./... ${isCI ? ["--timeout=45m"] : []}`;
389+
// Create a tmp directory for baseline tracking if enabled
390+
/** @type {string | undefined} */
391+
let trackingDir;
392+
/** @type {(() => void) | undefined} */
393+
let cleanupTracking;
394+
395+
if (baselineTrackingEnabled) {
396+
const tmpDir = tmp.dirSync({ prefix: "tsgo-baseline-tracking-", unsafeCleanup: true });
397+
trackingDir = tmpDir.name;
398+
cleanupTracking = tmpDir.removeCallback;
399+
}
400+
401+
try {
402+
const testEnv = {
403+
...goTestEnv,
404+
...(trackingDir ? { TSGO_BASELINE_TRACKING_DIR: trackingDir } : {}),
405+
};
406+
const $testWithTracking = $({ env: testEnv });
407+
await $testWithTracking`${gotestsum("tests")} ./... ${isCI ? ["--timeout=45m"] : []}`;
408+
409+
// Check for unused baselines after tests complete
410+
if (trackingDir) {
411+
const unusedBaselines = await checkUnusedBaselines(trackingDir);
412+
if (unusedBaselines.length > 0) {
413+
console.error(pc.red(`\nFound ${unusedBaselines.length} unused baseline file(s):`));
414+
for (const baseline of unusedBaselines.slice(0, 20)) {
415+
console.error(pc.red(` ${baseline}`));
416+
}
417+
if (unusedBaselines.length > 20) {
418+
console.error(pc.red(` ... and ${unusedBaselines.length - 20} more`));
419+
}
420+
421+
// Create .delete files for each unused baseline so baseline-accept can remove them
422+
for (const baseline of unusedBaselines) {
423+
const deleteFilePath = path.join(localBaseline, baseline + ".delete");
424+
await fs.promises.mkdir(path.dirname(deleteFilePath), { recursive: true });
425+
await fs.promises.writeFile(deleteFilePath, "");
426+
}
427+
console.error(pc.red(`\nRun 'hereby baseline-accept' to delete them.`));
428+
429+
throw new Error(`Found ${unusedBaselines.length} unused baseline file(s). Run 'hereby baseline-accept' to delete them.`);
430+
}
431+
}
432+
}
433+
finally {
434+
if (cleanupTracking) {
435+
cleanupTracking();
436+
}
437+
}
336438
}
337439

338440
export const test = task({

_packages/api/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"name": "@typescript/api",
44
"version": "1.0.0",
55
"type": "module",
6+
"engines": {
7+
"node": ">=20.19"
8+
},
69
"imports": {
710
"#symbolFlags": {
811
"@typescript/source": {
@@ -42,7 +45,7 @@
4245
"test": "node --test --experimental-strip-types --no-warnings --conditions @typescript/source ./test/**/*.test.ts"
4346
},
4447
"devDependencies": {
45-
"tinybench": "^3.1.1"
48+
"tinybench": "^6.0.0"
4649
},
4750
"dependencies": {
4851
"@typescript/ast": "1.0.0",

_packages/ast/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
"version": "1.0.0",
55
"description": "TypeScript AST definitions",
66
"type": "module",
7+
"engines": {
8+
"node": ">=20.19"
9+
},
710
"imports": {
811
"#syntaxKind": {
912
"@typescript/source": {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package encoder_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/testutil/baseline"
7+
)
8+
9+
func TestMain(m *testing.M) {
10+
defer baseline.Track()()
11+
m.Run()
12+
}

internal/astnav/testmain_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package astnav_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/testutil/baseline"
7+
)
8+
9+
func TestMain(m *testing.M) {
10+
defer baseline.Track()()
11+
m.Run()
12+
}

internal/checker/utilities.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ func CompareTypes(t1, t2 *Type) int {
491491
if c := CompareTypes(t1.AsIndexType().target, t2.AsIndexType().target); c != 0 {
492492
return c
493493
}
494-
if c := int(t1.AsIndexType().flags) - int(t2.AsIndexType().flags); c != 0 {
494+
if c := int(t1.AsIndexType().indexFlags) - int(t2.AsIndexType().indexFlags); c != 0 {
495495
return c
496496
}
497497
case t1.flags&TypeFlagsIndexedAccess != 0:

internal/compiler/fileInclude.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"sync"
66

77
"github.com/microsoft/typescript-go/internal/ast"
8-
"github.com/microsoft/typescript-go/internal/core"
98
"github.com/microsoft/typescript-go/internal/diagnostics"
109
"github.com/microsoft/typescript-go/internal/module"
1110
"github.com/microsoft/typescript-go/internal/scanner"
@@ -23,8 +22,6 @@ const (
2322
fileIncludeKindLibReferenceDirective
2423

2524
fileIncludeKindRootFile
26-
fileIncludeKindSourceFromProjectReference
27-
fileIncludeKindOutputFromProjectReference
2825
fileIncludeKindLibFile
2926
fileIncludeKindAutomaticTypeDirectiveFile
3027
)
@@ -192,15 +189,6 @@ func (r *FileIncludeReason) computeDiagnostic(program *Program, toFileName func(
192189
} else {
193190
return ast.NewCompilerDiagnostic(diagnostics.Root_file_specified_for_compilation)
194191
}
195-
case fileIncludeKindSourceFromProjectReference,
196-
fileIncludeKindOutputFromProjectReference:
197-
diag := core.IfElse(
198-
r.kind == fileIncludeKindOutputFromProjectReference,
199-
diagnostics.Output_from_referenced_project_0_included_because_module_is_specified_as_none,
200-
diagnostics.Source_from_referenced_project_0_included_because_module_is_specified_as_none,
201-
)
202-
referencedResolvedRef := program.projectReferenceFileMapper.getResolvedProjectReferences()[r.asIndex()]
203-
return ast.NewCompilerDiagnostic(diag, toFileName(referencedResolvedRef.ConfigName()))
204192
case fileIncludeKindAutomaticTypeDirectiveFile:
205193
data := r.asAutomaticTypeDirectiveFileData()
206194
if program.Options().Types != nil {
@@ -288,16 +276,6 @@ func (r *FileIncludeReason) toRelatedInfo(program *Program) *ast.Diagnostic {
288276
return tsoptions.CreateDiagnosticForNodeInSourceFile(config.ConfigFile.SourceFile, includeNode.AsNode(), diagnostics.File_is_matched_by_include_pattern_specified_here)
289277
}
290278
}
291-
case fileIncludeKindSourceFromProjectReference,
292-
fileIncludeKindOutputFromProjectReference:
293-
return tsoptions.CreateDiagnosticAtReferenceSyntax(
294-
config,
295-
r.asIndex(),
296-
core.IfElse(
297-
r.kind == fileIncludeKindOutputFromProjectReference,
298-
diagnostics.File_is_output_from_referenced_project_specified_here,
299-
diagnostics.File_is_source_from_referenced_project_specified_here,
300-
))
301279
case fileIncludeKindAutomaticTypeDirectiveFile:
302280
if program.Options().Types != nil {
303281
data := r.asAutomaticTypeDirectiveFileData()

internal/compiler/fileloader.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,24 @@ type fileLoader struct {
5050
pathForLibFileResolutions collections.SyncMap[tspath.Path, *libResolution]
5151
}
5252

53+
type redirectsFile struct {
54+
// Index of file at which this redirect file needs to be iterated
55+
index int
56+
fileName string
57+
path tspath.Path
58+
target tspath.Path
59+
}
60+
61+
var _ ast.HasFileName = (*redirectsFile)(nil)
62+
63+
func (r *redirectsFile) FileName() string {
64+
return r.fileName
65+
}
66+
67+
func (r *redirectsFile) Path() tspath.Path {
68+
return r.path
69+
}
70+
5371
type processedFiles struct {
5472
resolver *module.Resolver
5573
files []*ast.SourceFile
@@ -70,9 +88,9 @@ type processedFiles struct {
7088
outputFileToProjectReferenceSource map[tspath.Path]string
7189
// Key is a file path. Value is the list of files that redirect to it (same package, different install location)
7290
redirectTargetsMap map[tspath.Path][]string
73-
// Any paths involved in deduplication, including canonical paths and redirected paths
74-
deduplicatedPaths collections.Set[tspath.Path]
75-
finishedProcessing bool
91+
// filesByPath for redirect files
92+
redirectFilesByPath map[tspath.Path]*redirectsFile
93+
finishedProcessing bool
7694
}
7795

7896
type jsxRuntimeImportSpecifier struct {

0 commit comments

Comments
 (0)