{"version":3,"sources":["../../src/assertions/parseAssertions.ts"],"sourcesContent":["import type ts from \"typescript\";\n\nimport { getTypeSnapshot } from \"../utils/snapshot.js\";\nimport { parseTwoslashAssertion } from \"./parseTwoslashAssertion.js\";\nimport { Assertion, TwoSlashAssertion } from \"./types.js\";\nimport { Assertions, SyntaxError } from \"./types.js\";\n\nexport function parseAssertions(sourceFile: ts.SourceFile): Assertions {\n\tconst errorLines = new Set<number>();\n\tconst typeAssertions = new Map<number, Assertion>();\n\tconst syntaxErrors: SyntaxError[] = [];\n\tconst twoSlashAssertions: TwoSlashAssertion[] = [];\n\n\tconst { text } = sourceFile;\n\tconst commentRegexp = /\\/\\/(.*)/g;\n\tconst lineStarts = sourceFile.getLineStarts();\n\tlet curLine = 0;\n\n\twhile (true) {\n\t\tconst commentMatch = commentRegexp.exec(text);\n\t\tif (commentMatch === null) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// Match on the contents of that comment so we do nothing in a commented-out assertion,\n\t\t// i.e. `// foo; // $ExpectType number`\n\t\tconst comment = commentMatch[1];\n\t\t// eslint-disable-next-line regexp/no-unused-capturing-group\n\t\tconst matchExpect = /^\\s*\\$Expect(TypeSnapshot|Type|Error)( (.*))?$/.exec(\n\t\t\tcomment,\n\t\t) as [never, \"Error\" | \"Type\" | \"TypeSnapshot\", never, string?] | null;\n\t\tconst commentIndex = commentMatch.index;\n\t\tconst line = getLine(commentIndex);\n\t\tif (matchExpect) {\n\t\t\tconst directive = matchExpect[1];\n\t\t\tconst payload = matchExpect[3]?.trim();\n\t\t\tswitch (directive) {\n\t\t\t\tcase \"Error\":\n\t\t\t\t\terrorLines.add(line);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"Type\": {\n\t\t\t\t\tconst expected = payload;\n\t\t\t\t\tif (expected) {\n\t\t\t\t\t\ttypeAssertions.set(line, { assertionType: \"manual\", expected });\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsyntaxErrors.push({\n\t\t\t\t\t\t\tline,\n\t\t\t\t\t\t\ttype: \"MissingExpectType\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase \"TypeSnapshot\": {\n\t\t\t\t\tconst snapshotName = payload;\n\t\t\t\t\tif (snapshotName) {\n\t\t\t\t\t\ttypeAssertions.set(line, {\n\t\t\t\t\t\t\tassertionType: \"snapshot\",\n\t\t\t\t\t\t\texpected: getTypeSnapshot(sourceFile.fileName, snapshotName),\n\t\t\t\t\t\t\tsnapshotName,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsyntaxErrors.push({\n\t\t\t\t\t\t\tline,\n\t\t\t\t\t\t\ttype: \"MissingSnapshotName\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Maybe it's a twoslash assertion\n\t\t\tconst assertion = parseTwoslashAssertion(\n\t\t\t\tcomment,\n\t\t\t\tcommentIndex,\n\t\t\t\tline,\n\t\t\t\ttext,\n\t\t\t\tlineStarts,\n\t\t\t);\n\t\t\tif (assertion) {\n\t\t\t\tif (\"type\" in assertion) {\n\t\t\t\t\tsyntaxErrors.push(assertion);\n\t\t\t\t} else {\n\t\t\t\t\ttwoSlashAssertions.push(assertion);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\terrorLines,\n\t\tsyntaxErrors,\n\t\ttwoSlashAssertions,\n\t\ttypeAssertions,\n\t};\n\n\tfunction getLine(pos: number): number {\n\t\t// advance curLine to be the line preceding 'pos'\n\t\twhile (lineStarts[curLine + 1] <= pos) {\n\t\t\tcurLine++;\n\t\t}\n\n\t\t// If this is the first token on the line, it applies to the next line.\n\t\t// Otherwise, it applies to the text to the left of it.\n\t\treturn isFirstOnLine(text, lineStarts[curLine], pos)\n\t\t\t? curLine + 1\n\t\t\t: curLine;\n\t}\n}\n\nfunction isFirstOnLine(text: string, lineStart: number, pos: number): boolean {\n\tfor (let i = lineStart; i < pos; i++) {\n\t\tif (/\\S/.test(text[i])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n"],"mappings":";AAEA,SAAS,uBAAuB;AAChC,SAAS,8BAA8B;AAIhC,SAAS,gBAAgB,YAAuC;AACtE,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,iBAAiB,oBAAI,IAAuB;AAClD,QAAM,eAA8B,CAAC;AACrC,QAAM,qBAA0C,CAAC;AAEjD,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,gBAAgB;AACtB,QAAM,aAAa,WAAW,cAAc;AAC5C,MAAI,UAAU;AAEd,SAAO,MAAM;AACZ,UAAM,eAAe,cAAc,KAAK,IAAI;AAC5C,QAAI,iBAAiB,MAAM;AAC1B;AAAA,IACD;AAIA,UAAM,UAAU,aAAa,CAAC;AAE9B,UAAM,cAAc,iDAAiD;AAAA,MACpE;AAAA,IACD;AACA,UAAM,eAAe,aAAa;AAClC,UAAM,OAAO,QAAQ,YAAY;AACjC,QAAI,aAAa;AAChB,YAAM,YAAY,YAAY,CAAC;AAC/B,YAAM,UAAU,YAAY,CAAC,GAAG,KAAK;AACrC,cAAQ,WAAW;AAAA,QAClB,KAAK;AACJ,qBAAW,IAAI,IAAI;AACnB;AAAA,QAED,KAAK,QAAQ;AACZ,gBAAM,WAAW;AACjB,cAAI,UAAU;AACb,2BAAe,IAAI,MAAM,EAAE,eAAe,UAAU,SAAS,CAAC;AAAA,UAC/D,OAAO;AACN,yBAAa,KAAK;AAAA,cACjB;AAAA,cACA,MAAM;AAAA,YACP,CAAC;AAAA,UACF;AAEA;AAAA,QACD;AAAA,QAEA,KAAK,gBAAgB;AACpB,gBAAM,eAAe;AACrB,cAAI,cAAc;AACjB,2BAAe,IAAI,MAAM;AAAA,cACxB,eAAe;AAAA,cACf,UAAU,gBAAgB,WAAW,UAAU,YAAY;AAAA,cAC3D;AAAA,YACD,CAAC;AAAA,UACF,OAAO;AACN,yBAAa,KAAK;AAAA,cACjB;AAAA,cACA,MAAM;AAAA,YACP,CAAC;AAAA,UACF;AAEA;AAAA,QACD;AAAA,MACD;AAAA,IACD,OAAO;AAEN,YAAM,YAAY;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA,UAAI,WAAW;AACd,YAAI,UAAU,WAAW;AACxB,uBAAa,KAAK,SAAS;AAAA,QAC5B,OAAO;AACN,6BAAmB,KAAK,SAAS;AAAA,QAClC;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAEA,WAAS,QAAQ,KAAqB;AAErC,WAAO,WAAW,UAAU,CAAC,KAAK,KAAK;AACtC;AAAA,IACD;AAIA,WAAO,cAAc,MAAM,WAAW,OAAO,GAAG,GAAG,IAChD,UAAU,IACV;AAAA,EACJ;AACD;AAEA,SAAS,cAAc,MAAc,WAAmB,KAAsB;AAC7E,WAAS,IAAI,WAAW,IAAI,KAAK,KAAK;AACrC,QAAI,KAAK,KAAK,KAAK,CAAC,CAAC,GAAG;AACvB,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;","names":[]}