Skip to content

Commit 49925b8

Browse files
dependabot[bot]github-actions[bot]buke
authored
deps(deps): bump microsoft/typescript-go from 20bf4fc to 51d6a11 (#57)
* deps(deps): bump microsoft/typescript-go from `20bf4fc` to `51d6a11` Bumps [microsoft/typescript-go](https://github.com/microsoft/typescript-go) from `20bf4fc` to `51d6a11`. - [Commits](microsoft/typescript-go@20bf4fc...51d6a11) --- updated-dependencies: - dependency-name: microsoft/typescript-go dependency-version: 51d6a11318b737067b21596e0987cbbb79c9bf69 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * chore(sync): mirror internal packages into pkg/ (auto) (#58) Co-authored-by: buke <1013738+buke@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: buke <1013738+buke@users.noreply.github.com>
1 parent 0fc83aa commit 49925b8

35 files changed

+465
-166
lines changed

microsoft/typescript-go

Submodule typescript-go updated 39 files

pkg/ast/ast.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11001,7 +11001,6 @@ func (node *SourceFile) GetOrCreateToken(
1100111001
) *TokenNode {
1100211002
node.tokenCacheMu.Lock()
1100311003
defer node.tokenCacheMu.Unlock()
11004-
1100511004
loc := core.NewTextRange(pos, end)
1100611005
if node.tokenCache == nil {
1100711006
node.tokenCache = make(map[core.TextRange]*Node)
@@ -11014,7 +11013,9 @@ func (node *SourceFile) GetOrCreateToken(
1101411013
}
1101511014
return token
1101611015
}
11017-
11016+
if parent.Flags&NodeFlagsReparsed != 0 {
11017+
panic(fmt.Sprintf("Cannot create token from reparsed node of kind %v", parent.Kind))
11018+
}
1101811019
token := createToken(kind, node, pos, end, flags)
1101911020
token.Loc = loc
1102011021
token.Parent = parent

pkg/astnav/tokens.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ func getTokenAtPosition(
6565
// `left` tracks the lower boundary of the node/token that could be returned,
6666
// and is eventually the scanner's start position, if the scanner is used.
6767
left := 0
68-
// `allowReparsed` is set when we're navigating inside an AsExpression or
69-
// SatisfiesExpression, which allows visiting their reparsed children to reach
70-
// the actual identifier from JSDoc type assertions.
71-
allowReparsed := false
7268

7369
testNode := func(node *ast.Node) int {
7470
if node.Kind != ast.KindEndOfFile && node.End() == position && includePrecedingTokenAtEndPosition != nil {
@@ -92,15 +88,8 @@ func getTokenAtPosition(
9288
// We can't abort visiting children, so once a match is found, we set `next`
9389
// and do nothing on subsequent visits.
9490
if node != nil && next == nil {
95-
// Skip reparsed nodes unless:
96-
// 1. The node itself is AsExpression or SatisfiesExpression, OR
97-
// 2. We're already inside an AsExpression or SatisfiesExpression (allowReparsed=true)
98-
// These are special cases where reparsed nodes from JSDoc type assertions
99-
// should still be navigable to reach identifiers.
100-
isSpecialReparsed := node.Flags&ast.NodeFlagsReparsed != 0 &&
101-
(node.Kind == ast.KindAsExpression || node.Kind == ast.KindSatisfiesExpression)
102-
103-
if node.Flags&ast.NodeFlagsReparsed == 0 || isSpecialReparsed || allowReparsed {
91+
// Skip reparsed nodes
92+
if node.Flags&ast.NodeFlagsReparsed == 0 {
10493
result := testNode(node)
10594
switch result {
10695
case -1:
@@ -211,11 +200,6 @@ func getTokenAtPosition(
211200
current = next
212201
left = current.Pos()
213202
next = nil
214-
// When navigating into AsExpression or SatisfiesExpression, allow visiting
215-
// their reparsed children to reach identifiers from JSDoc type assertions.
216-
if current.Kind == ast.KindAsExpression || current.Kind == ast.KindSatisfiesExpression {
217-
allowReparsed = true
218-
}
219203
}
220204
}
221205

pkg/checker/checker.go

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10408,18 +10408,15 @@ func (c *Checker) getInstantiationExpressionType(exprType *Type, node *ast.Node)
1040810408
}
1040910409

1041010410
func (c *Checker) checkSatisfiesExpression(node *ast.Node) *Type {
10411-
c.checkSourceElement(node.Type())
10412-
return c.checkSatisfiesExpressionWorker(node.Expression(), node.Type(), CheckModeNormal)
10413-
}
10414-
10415-
func (c *Checker) checkSatisfiesExpressionWorker(expression *ast.Node, target *ast.Node, checkMode CheckMode) *Type {
10416-
exprType := c.checkExpressionEx(expression, checkMode)
10417-
targetType := c.getTypeFromTypeNode(target)
10411+
typeNode := node.Type()
10412+
c.checkSourceElement(typeNode)
10413+
exprType := c.checkExpression(node.Expression())
10414+
targetType := c.getTypeFromTypeNode(typeNode)
1041810415
if c.isErrorType(targetType) {
1041910416
return targetType
1042010417
}
10421-
errorNode := ast.FindAncestor(target.Parent, func(n *ast.Node) bool { return ast.IsSatisfiesExpression(n) })
10422-
c.checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, errorNode, expression, diagnostics.Type_0_does_not_satisfy_the_expected_type_1, nil)
10418+
errorNode := core.IfElse(typeNode.Flags&ast.NodeFlagsReparsed != 0, typeNode, node)
10419+
c.checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, errorNode, node.Expression(), diagnostics.Type_0_does_not_satisfy_the_expected_type_1, nil)
1042310420
return exprType
1042410421
}
1042510422

@@ -11371,21 +11368,13 @@ func (c *Checker) isOptionalPropertyDeclaration(node *ast.Node) bool {
1137111368
}
1137211369

1137311370
func (c *Checker) isPropertyDeclaredInAncestorClass(prop *ast.Symbol) bool {
11374-
if prop.Parent.Flags&ast.SymbolFlagsClass == 0 {
11375-
return false
11376-
}
11377-
classType := c.getDeclaredTypeOfSymbol(prop.Parent)
11378-
for {
11379-
baseTypes := c.getBaseTypes(classType)
11380-
if len(baseTypes) == 0 {
11381-
return false
11382-
}
11383-
classType = baseTypes[0]
11384-
superProperty := c.getPropertyOfType(classType, prop.Name)
11385-
if superProperty != nil && superProperty.ValueDeclaration != nil {
11386-
return true
11371+
if prop.Parent.Flags&ast.SymbolFlagsClass != 0 {
11372+
if baseTypes := c.getBaseTypes(c.getDeclaredTypeOfSymbol(prop.Parent)); len(baseTypes) != 0 {
11373+
superProperty := c.getPropertyOfType(baseTypes[0], prop.Name)
11374+
return superProperty != nil && superProperty.ValueDeclaration != nil
1138711375
}
1138811376
}
11377+
return false
1138911378
}
1139011379

1139111380
/**
@@ -11935,14 +11924,15 @@ func (c *Checker) checkAssertion(node *ast.Node, checkMode CheckMode) *Type {
1193511924
}
1193611925

1193711926
func (c *Checker) checkAssertionDeferred(node *ast.Node) {
11927+
typeNode := node.Type()
1193811928
exprType := c.getRegularTypeOfObjectLiteral(c.getBaseTypeOfLiteralType(c.assertionLinks.Get(node).exprType))
11939-
targetType := c.getTypeFromTypeNode(node.Type())
11929+
targetType := c.getTypeFromTypeNode(typeNode)
1194011930
if !c.isErrorType(targetType) {
1194111931
widenedType := c.getWidenedType(exprType)
1194211932
if !c.isTypeComparableTo(targetType, widenedType) {
1194311933
errNode := node
11944-
if node.Flags&ast.NodeFlagsReparsed != 0 {
11945-
errNode = node.Type()
11934+
if typeNode.Flags&ast.NodeFlagsReparsed != 0 {
11935+
errNode = typeNode
1194611936
}
1194711937
c.checkTypeComparableTo(exprType, targetType, errNode, diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first)
1194811938
}
Lines changed: 114 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,137 @@
11
import * as cp from "child_process";
22
import * as fs from "fs";
33
import path from "path";
4+
import * as readline from "readline";
45
import which from "which";
56

67
const failingTestsPath = path.join(import.meta.dirname, "failingTests.txt");
78
const crashingTestsPath = path.join(import.meta.dirname, "crashingTests.txt");
89

9-
function main() {
10+
interface TestEvent {
11+
Time?: string;
12+
Action: string;
13+
Package?: string;
14+
Test?: string;
15+
Output?: string;
16+
Elapsed?: number;
17+
}
18+
19+
async function main() {
1020
const go = which.sync("go");
11-
let testOutput: string;
21+
22+
let testProcess: cp.ChildProcess;
1223
try {
1324
// Run tests with TSGO_FOURSLASH_IGNORE_FAILING=1 to run all tests including those in failingTests.txt
14-
testOutput = cp.execFileSync(go, ["test", "-v", "./internal/fourslash/tests/gen"], {
15-
encoding: "utf-8",
25+
testProcess = cp.spawn(go, ["test", "-json", "./internal/fourslash/tests/gen"], {
26+
stdio: ["ignore", "pipe", "pipe"],
1627
env: { ...process.env, TSGO_FOURSLASH_IGNORE_FAILING: "1" },
1728
});
1829
}
1930
catch (error) {
20-
testOutput = (error as { stdout: string; }).stdout as string;
31+
throw new Error("Failed to spawn test process: " + error);
2132
}
22-
const panicRegex = /^panic/m;
23-
if (panicRegex.test(testOutput)) {
24-
throw new Error("Unrecovered panic detected in tests\n" + testOutput);
33+
34+
if (!testProcess.stdout || !testProcess.stderr) {
35+
throw new Error("Test process stdout or stderr is null");
2536
}
26-
const failRegex = /--- FAIL: ([\S]+)/gm;
37+
2738
const failingTests: string[] = [];
28-
const crashingRegex = /^=== (?:NAME|CONT) ([\S]+)\n.*InternalError.*$/gm;
2939
const crashingTests: string[] = [];
30-
let match;
40+
const testOutputs = new Map<string, string[]>();
41+
const allOutputs: string[] = [];
42+
let hadPanic = false;
3143

32-
while ((match = failRegex.exec(testOutput)) !== null) {
33-
failingTests.push(match[1]);
34-
}
35-
while ((match = crashingRegex.exec(testOutput)) !== null) {
36-
crashingTests.push(match[1]);
37-
}
44+
const rl = readline.createInterface({
45+
input: testProcess.stdout,
46+
crlfDelay: Infinity,
47+
});
48+
49+
rl.on("line", line => {
50+
try {
51+
const event: TestEvent = JSON.parse(line);
52+
53+
// Collect output for each test
54+
if (event.Action === "output" && event.Output) {
55+
allOutputs.push(event.Output);
56+
if (event.Test) {
57+
if (!testOutputs.has(event.Test)) {
58+
testOutputs.set(event.Test, []);
59+
}
60+
testOutputs.get(event.Test)!.push(event.Output);
61+
}
62+
63+
// Check for panics
64+
if (/^panic/m.test(event.Output)) {
65+
hadPanic = true;
66+
}
67+
}
68+
69+
// Process failed tests
70+
if (event.Action === "fail" && event.Test) {
71+
const outputs = testOutputs.get(event.Test) || [];
3872

39-
fs.writeFileSync(failingTestsPath, failingTests.sort((a, b) => a.localeCompare(b, "en-US")).join("\n") + "\n", "utf-8");
40-
fs.writeFileSync(crashingTestsPath, crashingTests.sort((a, b) => a.localeCompare(b, "en-US")).join("\n") + "\n", "utf-8");
73+
// Check if this is a crashing test (contains InternalError)
74+
const hasCrash = outputs.some(line => line.includes("InternalError"));
75+
if (hasCrash) {
76+
crashingTests.push(event.Test);
77+
}
78+
79+
// A test is only considered a baseline-only failure if ALL error messages
80+
// are baseline-related. Any non-baseline error message means it's a real failure.
81+
const baselineMessagePatterns = [
82+
/^\s*baseline\.go:\d+: the baseline file .* has changed\./,
83+
/^\s*baseline\.go:\d+: new baseline created at /,
84+
/^\s*baseline\.go:\d+: the baseline file .* does not exist in the TypeScript submodule/,
85+
/^\s*baseline\.go:\d+: the baseline file .* does not match the reference in the TypeScript submodule/,
86+
];
87+
88+
// Check each output line that looks like an error message
89+
// Error messages from Go tests typically contain ".go:" with a line number
90+
const errorLines = outputs.filter(line => /^\s*\w+\.go:\d+:/.test(line));
91+
92+
// If there are no error lines, it's a real failure.
93+
// If all error lines match baseline patterns, it's a baseline-only failure
94+
const isBaselineOnlyFailure = errorLines.length > 0 &&
95+
errorLines.every(line => baselineMessagePatterns.some(pattern => pattern.test(line)));
96+
97+
if (!isBaselineOnlyFailure) {
98+
failingTests.push(event.Test);
99+
}
100+
}
101+
}
102+
catch (e) {
103+
// Not JSON, possibly stderr or other output - ignore
104+
}
105+
});
106+
107+
testProcess.stderr.on("data", data => {
108+
// Check stderr for panics too
109+
const output = data.toString();
110+
allOutputs.push(output);
111+
if (/^panic/m.test(output)) {
112+
hadPanic = true;
113+
}
114+
});
115+
116+
await new Promise<void>((resolve, reject) => {
117+
testProcess.on("close", code => {
118+
if (hadPanic) {
119+
reject(new Error("Unrecovered panic detected in tests\n" + allOutputs.join("")));
120+
return;
121+
}
122+
123+
fs.writeFileSync(failingTestsPath, failingTests.sort((a, b) => a.localeCompare(b, "en-US")).join("\n") + "\n", "utf-8");
124+
fs.writeFileSync(crashingTestsPath, crashingTests.sort((a, b) => a.localeCompare(b, "en-US")).join("\n") + "\n", "utf-8");
125+
resolve();
126+
});
127+
128+
testProcess.on("error", error => {
129+
reject(error);
130+
});
131+
});
41132
}
42133

43-
main();
134+
main().catch(error => {
135+
console.error("Error:", error);
136+
process.exit(1);
137+
});

pkg/ls/folding.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,7 @@ func (l *LanguageService) addRegionOutliningSpans(sourceFile *ast.SourceFile) []
109109
}
110110

111111
func visitNode(ctx context.Context, n *ast.Node, depthRemaining int, sourceFile *ast.SourceFile, l *LanguageService) []*lsproto.FoldingRange {
112-
if depthRemaining == 0 {
113-
return nil
114-
}
115-
if ctx.Err() != nil {
112+
if n.Flags&ast.NodeFlagsReparsed != 0 || depthRemaining == 0 || ctx.Err() != nil {
116113
return nil
117114
}
118115
foldingRange := make([]*lsproto.FoldingRange, 0, 40)

pkg/ls/hover.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,24 @@ func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, de
109109
}
110110
comments := tag.Comments()
111111
if tag.Kind == ast.KindJSDocTag && tag.TagName().Text() == "example" {
112-
b.WriteString("\n")
113112
commentText := strings.TrimRight(getCommentText(comments), " \t\r\n")
113+
if strings.HasPrefix(commentText, "<caption>") {
114+
if captionEnd := strings.Index(commentText, "</caption>"); captionEnd > 0 {
115+
b.WriteString(" — ")
116+
b.WriteString(commentText[len("<caption>"):captionEnd])
117+
commentText = commentText[captionEnd+len("</caption>"):]
118+
// Trim leading blank lines from commentText
119+
for {
120+
s1 := strings.TrimLeft(commentText, " \t")
121+
s2 := strings.TrimLeft(s1, "\r\n")
122+
if len(s1) == len(s2) {
123+
break
124+
}
125+
commentText = s2
126+
}
127+
}
128+
}
129+
b.WriteString("\n")
114130
if len(commentText) > 6 && strings.HasPrefix(commentText, "```") && strings.HasSuffix(commentText, "```") && strings.Contains(commentText, "\n") {
115131
b.WriteString(commentText)
116132
b.WriteString("\n")

pkg/parser/parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ func ParseIsolatedEntityName(text string) *ast.EntityName {
207207

208208
func (p *Parser) initializeState(opts ast.SourceFileParseOptions, sourceText string, scriptKind core.ScriptKind) {
209209
if scriptKind == core.ScriptKindUnknown {
210-
panic("ScriptKind must be specified when parsing source files.")
210+
panic("ScriptKind must be specified when parsing source file: " + opts.FileName)
211211
}
212212

213213
if p.scanner == nil {

0 commit comments

Comments
 (0)