Skip to content

fourslash baselines and VerifyBaselinefindAllReferences #1274

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 14 commits into from
Jul 8, 2025
Merged
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ linters:
type: module

exclusions:
rules:
- path: internal/fourslash/tests/gen/
linters: misspell

presets:
- comments
- std-error-handling
Expand Down
8 changes: 8 additions & 0 deletions internal/collections/multimap.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ type MultiMap[K comparable, V comparable] struct {
M map[K][]V
}

func GroupBy[K comparable, V comparable](items []V, groupId func(V) K) *MultiMap[K, V] {
m := &MultiMap[K, V]{}
for _, item := range items {
m.Add(groupId(item), item)
}
return m
}

func (s *MultiMap[K, V]) Has(key K) bool {
_, ok := s.M[key]
return ok
Expand Down
59 changes: 54 additions & 5 deletions internal/fourslash/_scripts/convertFourslash.mts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function parseFileContent(filename: string, content: string): GoTest | undefined
const sourceFile = ts.createSourceFile("temp.ts", content, ts.ScriptTarget.Latest, true /*setParentNodes*/);
const statements = sourceFile.statements;
const goTest: GoTest = {
name: filename.replace(".ts", ""),
name: filename.replace(".ts", "").replace(".", ""),
content: getTestInput(content),
commands: [],
};
Expand Down Expand Up @@ -141,9 +141,16 @@ function parseFourslashStatement(statement: ts.Statement): Cmd[] | undefined {
console.error(`Expected identifiers for namespace and function, got ${namespace.getText()} and ${func.getText()}`);
return undefined;
}
// `verify.completions(...)`
if (namespace.text === "verify" && func.text === "completions") {
return parseVerifyCompletionsArgs(callExpression.arguments);
// `verify.(...)`
if (namespace.text === "verify") {
switch (func.text) {
case "completions":
// `verify.completions(...)`
return parseVerifyCompletionsArgs(callExpression.arguments);
case "baselineFindAllReferences":
// `verify.baselineFindAllReferences(...)`
return [parseBaselineFindAllReferencesArgs(callExpression.arguments)];
}
}
// `goTo....`
if (namespace.text === "goTo") {
Expand Down Expand Up @@ -606,6 +613,27 @@ function parseExpectedCompletionItem(expr: ts.Expression): string | undefined {
return undefined; // Unsupported expression type
}

function parseBaselineFindAllReferencesArgs(args: readonly ts.Expression[]): VerifyBaselineFindAllReferencesCmd {
const newArgs = [];
for (const arg of args) {
if (ts.isStringLiteral(arg)) {
newArgs.push(getGoStringLiteral(arg.text));
}
else if (arg.getText() === "...test.ranges()") {
return {
kind: "verifyBaselineFindAllReferences",
markers: [],
ranges: true,
};
}
}

return {
kind: "verifyBaselineFindAllReferences",
markers: newArgs,
};
}

function parseKind(expr: ts.Expression): string | undefined {
if (!ts.isStringLiteral(expr)) {
console.error(`Expected string literal for kind, got ${expr.getText()}`);
Expand Down Expand Up @@ -732,6 +760,18 @@ interface VerifyCompletionsArgs {
unsorted?: string;
}

interface VerifyBaselineFindAllReferencesCmd {
kind: "verifyBaselineFindAllReferences";
markers: string[];
ranges?: boolean;
}

interface VerifyBaselineFindAllReferencesCmd {
kind: "verifyBaselineFindAllReferences";
markers: string[];
ranges?: boolean;
}

interface GoToCmd {
kind: "goTo";
// !!! `selectRange` and `rangeStart` require parsing variables and `test.ranges()[n]`
Expand All @@ -744,7 +784,7 @@ interface EditCmd {
goStatement: string;
}

type Cmd = VerifyCompletionsCmd | GoToCmd | EditCmd;
type Cmd = VerifyCompletionsCmd | VerifyBaselineFindAllReferencesCmd | GoToCmd | EditCmd;

function generateVerifyCompletions({ marker, args, isNewIdentifierLocation }: VerifyCompletionsCmd): string {
let expectedList = "nil";
Expand All @@ -770,6 +810,13 @@ function generateVerifyCompletions({ marker, args, isNewIdentifierLocation }: Ve
return `f.VerifyCompletions(t, ${marker}, ${expectedList})`;
}

function generateBaselineFindAllReferences({ markers, ranges }: VerifyBaselineFindAllReferencesCmd): string {
if (ranges || markers.length === 0) {
return `f.VerifyBaselineFindAllReferences(t)`;
}
return `f.VerifyBaselineFindAllReferences(t, ${markers.join(", ")})`;
}

function generateGoToCommand({ funcName, args }: GoToCmd): string {
const funcNameCapitalized = funcName.charAt(0).toUpperCase() + funcName.slice(1);
return `f.GoTo${funcNameCapitalized}(t, ${args.join(", ")})`;
Expand All @@ -779,6 +826,8 @@ function generateCmd(cmd: Cmd): string {
switch (cmd.kind) {
case "verifyCompletions":
return generateVerifyCompletions(cmd as VerifyCompletionsCmd);
case "verifyBaselineFindAllReferences":
return generateBaselineFindAllReferences(cmd as VerifyBaselineFindAllReferencesCmd);
case "goTo":
return generateGoToCommand(cmd as GoToCmd);
case "edit":
Expand Down
21 changes: 21 additions & 0 deletions internal/fourslash/_scripts/failingTests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,18 @@ TestCompletionsTriggerCharacter
TestCompletionsUniqueSymbol1
TestCompletionsWithStringReplacementMode1
TestExportEqualCallableInterface
TestFindAllReferencesTripleSlash
TestFindAllRefs_importType_typeofImport
TestFindAllRefsCommonJsRequire
TestFindAllRefsCommonJsRequire2
TestFindAllRefsCommonJsRequire3
TestFindAllRefsExportEquals
TestFindAllRefsForDefaultExport03
TestFindAllRefsJsDocImportTag
TestFindAllRefsModuleDotExports
TestFindAllRefsReExport_broken
TestFindAllReferencesUmdModuleAsGlobalConst
TestFindReferencesAfterEdit
TestGetJavaScriptCompletions1
TestGetJavaScriptCompletions10
TestGetJavaScriptCompletions11
Expand Down Expand Up @@ -209,6 +221,7 @@ TestJsDocFunctionSignatures3
TestJsDocGenerics1
TestJsdocExtendsTagCompletion
TestJsdocImplementsTagCompletion
TestJsdocLink_findAllReferences1
TestJsdocOverloadTagCompletion
TestJsdocParamTagSpecialKeywords
TestJsdocParameterNameCompletion
Expand All @@ -223,6 +236,8 @@ TestJsdocTypedefTag2
TestJsdocTypedefTagNamespace
TestJsdocTypedefTagTypeExpressionCompletion
TestJsxAriaLikeCompletions
TestJsxFindAllReferencesOnRuntimeImportWithPaths1
TestLocalGetReferences
TestJsxQualifiedTagCompletion
TestMemberListErrorRecovery
TestMemberListInWithBlock
Expand Down Expand Up @@ -277,6 +292,11 @@ TestPathCompletionsTypesVersionsWildcard3
TestPathCompletionsTypesVersionsWildcard4
TestPathCompletionsTypesVersionsWildcard5
TestPathCompletionsTypesVersionsWildcard6
TestReferencesForExportedValues
TestReferencesInComment
TestReferencesInEmptyFile
TestReferencesForStatementKeywords
TestReferencesIsAvailableThroughGlobalNoCrash
TestStringCompletionsImportOrExportSpecifier
TestStringCompletionsVsEscaping
TestStringLiteralTypeCompletionsInTypeArgForNonGeneric1
Expand All @@ -286,6 +306,7 @@ TestTripleSlashRefPathCompletionExtensionsAllowJSFalse
TestTripleSlashRefPathCompletionExtensionsAllowJSTrue
TestTripleSlashRefPathCompletionHiddenFile
TestTripleSlashRefPathCompletionRootdirs
TestTslibFindAllReferencesOnRuntimeImportWithPaths1
TestTsxCompletion12
TestTsxCompletion13
TestTsxCompletion14
Expand Down
Loading
Loading