in src/rules/expectRule.ts [238:288]
function parseAssertions(sourceFile: SourceFile): Assertions {
const errorLines = new Set<number>();
const typeAssertions = new Map<number, string>();
const duplicates: number[] = [];
const { text } = sourceFile;
const commentRegexp = /\/\/(.*)/g;
const lineStarts = sourceFile.getLineStarts();
let curLine = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
const commentMatch = commentRegexp.exec(text);
if (commentMatch === null) {
break;
}
// Match on the contents of that comment so we do nothing in a commented-out assertion,
// i.e. `// foo; // $ExpectType number`
const match = /^ \$Expect((Type (.*))|Error)$/.exec(commentMatch[1]);
if (match === null) {
continue;
}
const line = getLine(commentMatch.index);
if (match[1] === "Error") {
if (errorLines.has(line)) {
duplicates.push(line);
}
errorLines.add(line);
} else {
const expectedType = match[3];
// Don't bother with the assertion if there are 2 assertions on 1 line. Just fail for the duplicate.
if (typeAssertions.delete(line)) {
duplicates.push(line);
} else {
typeAssertions.set(line, expectedType);
}
}
}
return { errorLines, typeAssertions, duplicates };
function getLine(pos: number): number {
// advance curLine to be the line preceding 'pos'
while (lineStarts[curLine + 1] <= pos) {
curLine++;
}
// If this is the first token on the line, it applies to the next line.
// Otherwise, it applies to the text to the left of it.
return isFirstOnLine(text, lineStarts[curLine], pos) ? curLine + 1 : curLine;
}
}