microsoft/TypeScript · error · Error
You need to change the source code of fourslash test to use
Error message
You need to change the source code of fourslash test to use replaceWithSemanticClassifications
What it means
Thrown unconditionally by replaceWithSemanticClassifications to force the test author to stop using the auto-replacement helper. The method computes the semantic-classification assertions and builds a replacement string, but the file-rewrite logic below the throw is commented out — the throw is the intended behaviour. It exists so legacy fourslash tests calling verify.replaceWithSemanticClassifications("2020") are flagged for manual migration to explicit classification assertions.
Source
Thrown at src/harness/fourslashImpl.ts:3216
expected.join(","),
actual.fileNames!.map(file => {
return file.replace(this.basePath + "/", "");
}).join(","),
);
}
}
public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty): void {
const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format);
const replacement = [`const c2 = classification("2020");`, `verify.semanticClassificationsAre("2020",`];
for (const a of actual) {
const identifier = this.classificationToIdentifier(a.classificationType as number);
const text = this.activeFile.content.slice(a.textSpan.start, a.textSpan.start + a.textSpan.length);
replacement.push(` c2.semanticToken("${identifier}", "${text}"), `);
}
replacement.push(");");
throw new Error("You need to change the source code of fourslash test to use replaceWithSemanticClassifications");
// const fs = require("fs");
// const testfilePath = this.originalInputFileName.slice(1);
// const testfile = fs.readFileSync(testfilePath, "utf8");
// const newfile = testfile.replace("verify.replaceWithSemanticClassifications(\"2020\")", replacement.join("\n"));
// fs.writeFileSync(testfilePath, newfile);
}
public verifyEncodedSyntacticClassificationsLength(expected: number): void {
const actual = this.languageService.getEncodedSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length));
if (actual.spans.length !== expected) {
this.raiseError(`encodedSyntacticClassificationsLength failed - expected total spans to be ${expected} got ${actual.spans.length}`);
}
}
public verifyEncodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, expected: number): void {
const actual = this.languageService.getEncodedSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format);
if (actual.spans.length !== expected) {
View on GitHub (pinned to b465fdbfe1)
Solutions
- Run the test and capture the replacement strings printed/emitted before the throw — they contain the c2.semanticToken(...) lines and the verify.semanticClassificationsAre call.
- Paste those generated lines into the test source, replacing the verify.replaceWithSemanticClassifications("2020") call.
- Remove the replaceWithSemanticClassifications call entirely so the test now uses verify.semanticClassificationsAre with explicit token assertions.
- If the test is not yours, check for an upstream migration in a newer TypeScript revision.
Example fix
// before
verify.replaceWithSemanticClassifications("2020");
// after — generated lines pasted into the test
verify.semanticClassificationsAre("2020",
c2.semanticToken("keyword", "const"),
c2.semanticToken("identifier", "x"),
); Defensive patterns
Strategy: validation
Validate before calling
// Never call this in committed tests — it is a one-shot migration helper. // If you must run it, do so in a throwaway branch and capture stdout before the throw.
Try / catch
try {
verify.replaceWithSemanticClassifications("2020");
} catch (e) {
// This always throws; capture the generated replacement lines from the
// partially-built `replacement` array via a debug breakpoint, then migrate manually.
} Prevention
- Treat replaceWithSemanticClassifications as a one-time migration tool, not a standing assertion.
- After migration, replace the call with explicit verify.semanticClassificationsAre assertions.
When it happens
Trigger: A fourslash test contains verify.replaceWithSemanticClassifications("2020") (mapped to state.replaceWithSemanticClassifications). The method always throws regardless of file content because the migration scaffolding beneath it is disabled.
Common situations: Encountered when running an old fourslash test that was never migrated from the old classification verification style. The test was designed to be run once to generate assertions, then the generated output pasted into the test body.
Related errors
- DeprecationError: '${name}' has been deprecated since v${sin
- verifyCurrentLineContent\n
- verifyFileContent in file '${fileName}' failed:\n${showTextD
- verifyTextAtCaretIs\n
- Exactly one refactor range is allowed per test.
AI-assisted analysis of microsoft/TypeScript@b465fdbfe1 (2026-08-12).
Data as JSON: /api/errors/d32c2063361e3cee.
Report an issue: GitHub.