• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / js-slang / 23995741899

05 Apr 2026 06:14AM UTC coverage: 77.093% (+0.002%) from 77.091%
23995741899

push

github

web-flow
Upgrade to TypeScript 6 and Prettier improvements (#1936)

* Upgrade TypeScript to v6

* Fix import source

* Fix tsconfig

* Fix preexisting type errors

* Remove scm-slang

* Bump node types

* Fix tsconfig

* Fix node types specifier

* Enable trailing commas

* Enable semicolons

* Check and commit files with changed line numbers

* Update Yarn to 4.13.0

* Remove unneeded sicp package deps

3112 of 4282 branches covered (72.68%)

Branch coverage included in aggregate %.

3761 of 5218 new or added lines in 152 files covered. (72.08%)

26 existing lines in 9 files now uncovered.

7136 of 9011 relevant lines covered (79.19%)

175254.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.21
/src/parser/utils.ts
1
import {
2
  parse as acornParse,
3
  parseExpressionAt as acornParseAt,
4
  type Comment,
5
  ecmaVersion,
6
  type Node,
7
  type Position,
8
} from 'acorn';
9
import { parse as acornLooseParse } from 'acorn-loose';
10
import type { Program, SourceLocation } from 'estree';
11

12
import type { Context } from '..';
13
import { DEFAULT_ECMA_VERSION } from '../constants';
14
import type { SourceError } from '../errors/base';
15
import { validateAndAnnotate } from '../validator/validator';
16
import { MissingSemicolonError, TrailingCommaError } from './errors';
17
import type { AcornOptions, BabelOptions } from './types';
18

19
/**
20
 * Generates options object for acorn parser
21
 *
22
 * @param ecmaVersion ECMA version
23
 * @param errors error container
24
 * @param throwOnError throw on error if true else push to error container and resume exec
25
 * @param options partial acorn options
26
 * @returns
27
 */
28
export const createAcornParserOptions = (
65✔
29
  ecmaVersion: ecmaVersion,
30
  errors?: SourceError[],
31
  options?: Partial<AcornOptions>,
32
  throwOnError?: boolean,
33
): AcornOptions => ({
4,970✔
34
  ecmaVersion,
35
  sourceType: 'module',
36
  locations: true,
37
  onInsertedSemicolon(_tokenEndPos: number, tokenPos: Position) {
38
    const error = new MissingSemicolonError(
42✔
39
      positionToSourceLocation(tokenPos, options?.sourceFile),
40
    );
41
    if (throwOnError) throw error;
42!
42
    errors?.push(error);
42✔
43
  },
44
  onTrailingComma(_tokenEndPos: number, tokenPos: Position) {
45
    const error = new TrailingCommaError(positionToSourceLocation(tokenPos, options?.sourceFile));
3✔
46
    if (throwOnError) throw error;
3!
47
    errors?.push(error);
3✔
48
  },
49
  ...options,
50
});
51

52
/**
53
 * Parses a single expression at a specified offset
54
 *
55
 * @param programStr program string
56
 * @param offset position offset
57
 * @param ecmaVersion ECMA version
58
 * @returns acorn AST Node if parse succeeds else null
59
 */
60
export function parseAt(
61
  programStr: string,
62
  offset: number,
63
  ecmaVersion: ecmaVersion = DEFAULT_ECMA_VERSION,
148✔
64
): Node | null {
65
  try {
148✔
66
    return acornParseAt(programStr, offset, { ecmaVersion });
148✔
67
  } catch {
68
    return null;
27✔
69
  }
70
}
71

72
/**
73
 * Parse a program, returning alongside comments found within that program
74
 *
75
 * @param programStr program string
76
 * @param ecmaVersion ECMA version
77
 * @returns tuple consisting of the parsed program, and a list of comments found within the program string
78
 */
79
export function parseWithComments(
80
  programStr: string,
81
  ecmaVersion: ecmaVersion = DEFAULT_ECMA_VERSION,
44✔
82
): [Program, Comment[]] {
83
  let comments: Comment[] = [];
44✔
84
  const acornOptions: AcornOptions = createAcornParserOptions(
44✔
85
    ecmaVersion,
86
    undefined,
87
    {
88
      onComment: comments,
89
    },
90
    undefined,
91
  );
92

93
  let ast: Program | undefined;
94
  try {
44✔
95
    ast = acornParse(programStr, acornOptions) as unknown as Program;
44✔
96
  } catch {
97
    comments = [];
7✔
98
    ast = acornLooseParse(programStr, acornOptions);
7✔
99
  }
100

101
  return [ast, comments];
44✔
102
}
103

104
/**
105
 * Parse program with error-tolerant acorn parser
106
 *
107
 * @param programStr program string
108
 * @param context js-slang context
109
 * @returns ast for program string
110
 */
111
export function looseParse(programStr: string, context: Context): Program {
112
  return acornLooseParse(
45✔
113
    programStr,
114
    createAcornParserOptions(DEFAULT_ECMA_VERSION, context.errors),
115
  ) as unknown as Program;
116
}
117

118
/**
119
 * TODO
120
 *
121
 * @param programStr program string
122
 * @param context js-slang context
123
 * @returns ast for program string
124
 */
125
export function typedParse(programStr: string, context: Context): Program {
NEW
126
  const ast: Program = looseParse(programStr, context);
×
NEW
127
  return validateAndAnnotate(ast, context);
×
128
}
129

130
/**
131
 * Converts acorn parser Position object to SourceLocation object
132
 *
133
 * @param position acorn Position object
134
 * @returns SourceLocation
135
 */
136
export const positionToSourceLocation = (position: Position, source?: string): SourceLocation => ({
79✔
137
  start: { ...position },
138
  end: { ...position, column: position.column + 1 },
139
  source,
140
});
141

142
export const defaultBabelOptions: BabelOptions = {
65✔
143
  sourceType: 'module',
144
  plugins: ['typescript', 'estree'],
145
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc