{"record":{"id":"d32c2063361e3cee","repo":"microsoft/TypeScript","slug":"you-need-to-change-the-source-code-of-fourslash-te","errorCode":null,"errorMessage":"You need to change the source code of fourslash test to use replaceWithSemanticClassifications","messagePattern":"You need to change the source code of fourslash test to use replaceWithSemanticClassifications","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/harness/fourslashImpl.ts","lineNumber":3216,"sourceCode":"                expected.join(\",\"),\r\n                actual.fileNames!.map(file => {\r\n                    return file.replace(this.basePath + \"/\", \"\");\r\n                }).join(\",\"),\r\n            );\r\n        }\r\n    }\r\n\r\n    public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty): void {\r\n        const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format);\r\n        const replacement = [`const c2 = classification(\"2020\");`, `verify.semanticClassificationsAre(\"2020\",`];\r\n        for (const a of actual) {\r\n            const identifier = this.classificationToIdentifier(a.classificationType as number);\r\n            const text = this.activeFile.content.slice(a.textSpan.start, a.textSpan.start + a.textSpan.length);\r\n            replacement.push(`    c2.semanticToken(\"${identifier}\", \"${text}\"), `);\r\n        }\r\n        replacement.push(\");\");\r\n\r\n        throw new Error(\"You need to change the source code of fourslash test to use replaceWithSemanticClassifications\");\r\n\r\n        // const fs = require(\"fs\");\r\n        // const testfilePath = this.originalInputFileName.slice(1);\r\n        // const testfile = fs.readFileSync(testfilePath, \"utf8\");\r\n        // const newfile = testfile.replace(\"verify.replaceWithSemanticClassifications(\\\"2020\\\")\", replacement.join(\"\\n\"));\r\n        // fs.writeFileSync(testfilePath, newfile);\r\n    }\r\n\r\n    public verifyEncodedSyntacticClassificationsLength(expected: number): void {\r\n        const actual = this.languageService.getEncodedSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length));\r\n        if (actual.spans.length !== expected) {\r\n            this.raiseError(`encodedSyntacticClassificationsLength failed - expected total spans to be ${expected} got ${actual.spans.length}`);\r\n        }\r\n    }\r\n\r\n    public verifyEncodedSemanticClassificationsLength(format: ts.SemanticClassificationFormat, expected: number): void {\r\n        const actual = this.languageService.getEncodedSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length), format);\r\n        if (actual.spans.length !== expected) {\r","sourceCodeStart":3198,"sourceCodeEnd":3234,"githubUrl":"https://github.com/microsoft/TypeScript/blob/b465fdbfe175304d9b977da137b2c178ae1091d3/src/harness/fourslashImpl.ts#L3198-L3234","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nverify.replaceWithSemanticClassifications(\"2020\");\n// after — generated lines pasted into the test\nverify.semanticClassificationsAre(\"2020\",\n    c2.semanticToken(\"keyword\", \"const\"),\n    c2.semanticToken(\"identifier\", \"x\"),\n);","handlingStrategy":"validation","validationCode":"// Never call this in committed tests — it is a one-shot migration helper.\n// If you must run it, do so in a throwaway branch and capture stdout before the throw.","typeGuard":null,"tryCatchPattern":"try {\n    verify.replaceWithSemanticClassifications(\"2020\");\n} catch (e) {\n    // This always throws; capture the generated replacement lines from the\n    // partially-built `replacement` array via a debug breakpoint, then migrate manually.\n}","preventionTips":["Treat replaceWithSemanticClassifications as a one-time migration tool, not a standing assertion.","After migration, replace the call with explicit verify.semanticClassificationsAre assertions."],"tags":["fourslash","migration","semantic-classification","test-authoring"],"backgroundTag":null,"analyzedSha":"b465fdbfe175304d9b977da137b2c178ae1091d3","analyzedAt":"2026-08-12T05:38:42.698Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}