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

ota-meshi / jsonc-eslint-parser / 17888386344

21 Sep 2025 03:28AM UTC coverage: 88.63%. Remained the same
17888386344

push

github

web-flow
chore: release jsonc-eslint-parser (#242)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

308 of 366 branches covered (84.15%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 1 file covered. (100.0%)

604 of 663 relevant lines covered (91.1%)

63.98 hits per line

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

88.78
/src/utils/ast.ts
1
import type {
2
  JSONNode,
3
  JSONExpression,
4
  JSONNumberIdentifier,
5
  JSONIdentifier,
6
  JSONObjectExpression,
7
  JSONArrayExpression,
8
  JSONUnaryExpression,
9
  JSONNumberLiteral,
10
  JSONExpressionStatement,
11
  JSONProgram,
12
  JSONUndefinedIdentifier,
13
  JSONTemplateLiteral,
14
  JSONTemplateElement,
15
  JSONStringLiteral,
16
  JSONKeywordLiteral,
17
  JSONRegExpLiteral,
18
  JSONBigIntLiteral,
19
  JSONLiteral,
20
  JSONProperty,
21
  JSONBinaryExpression,
22
} from "../parser/ast";
23

24
/**
25
 * Checks if given node is JSONExpression
26
 */
27
export function isExpression<N extends JSONNode>(
1✔
28
  node: N,
29
): node is N & JSONExpression {
30
  if (node.type === "JSONIdentifier" || node.type === "JSONLiteral") {
11✔
31
    const parent = node.parent!;
6✔
32
    if (parent.type === "JSONProperty" && parent.key === node) {
6✔
33
      return false;
2✔
34
    }
35
    return true;
4✔
36
  }
37
  if (
5✔
38
    node.type === "JSONObjectExpression" ||
15✔
39
    node.type === "JSONArrayExpression" ||
40
    node.type === "JSONUnaryExpression" ||
41
    node.type === "JSONTemplateLiteral" ||
42
    node.type === "JSONBinaryExpression"
43
  ) {
44
    return true;
4✔
45
  }
46
  return false;
1✔
47
}
48

49
/**
50
 * Checks if given node is JSONNumberIdentifier
51
 */
52
export function isNumberIdentifier(
1✔
53
  node: JSONIdentifier,
54
): node is JSONNumberIdentifier {
55
  return (
×
56
    isExpression(node) && (node.name === "Infinity" || node.name === "NaN")
×
57
  );
58
}
59

60
/**
61
 * Checks if given node is JSONUndefinedIdentifier
62
 */
63
export function isUndefinedIdentifier(
1✔
64
  node: JSONIdentifier,
65
): node is JSONUndefinedIdentifier {
66
  return isExpression(node) && node.name === "undefined";
×
67
}
68

69
export type JSONValue =
70
  | string
71
  | number
72
  | boolean
73
  | null
74
  | undefined
75
  | JSONObjectValue
76
  | JSONValue[]
77
  | RegExp
78
  | bigint;
79
export type JSONObjectValue = { [key: string]: JSONValue };
80

81
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- any
82
const resolver: { [key in JSONNode["type"]]: (node: any) => JSONValue } = {
1✔
83
  Program(node: JSONProgram) {
84
    if (
45✔
85
      node.body.length !== 1 ||
90✔
86
      node.body[0].type !== "JSONExpressionStatement"
87
    ) {
88
      throw new Error("Illegal argument");
1✔
89
    }
90
    return getStaticJSONValue(node.body[0]);
44✔
91
  },
92
  JSONExpressionStatement(node: JSONExpressionStatement) {
93
    return getStaticJSONValue(node.expression);
44✔
94
  },
95
  JSONObjectExpression(node: JSONObjectExpression) {
96
    const object: JSONObjectValue = {};
21✔
97
    for (const prop of node.properties) {
21✔
98
      Object.assign(object, getStaticJSONValue(prop));
25✔
99
    }
100
    return object;
21✔
101
  },
102
  JSONProperty(node: JSONProperty) {
103
    const keyName =
104
      node.key.type === "JSONLiteral" ? `${node.key.value}` : node.key.name;
25✔
105
    return {
25✔
106
      [keyName]: getStaticJSONValue(node.value),
107
    };
108
  },
109
  JSONArrayExpression(node: JSONArrayExpression) {
110
    const array: JSONValue[] = [];
22✔
111
    for (let index = 0; index < node.elements.length; index++) {
22✔
112
      const element = node.elements[index];
67✔
113
      if (element) {
67✔
114
        array[index] = getStaticJSONValue(element);
60✔
115
      }
116
    }
117
    return array;
22✔
118
  },
119
  JSONLiteral(node: JSONLiteral) {
120
    if (node.regex) {
68✔
121
      try {
2✔
122
        return new RegExp(node.regex.pattern, node.regex.flags);
2✔
123
      } catch {
124
        return `/${node.regex.pattern}/${node.regex.flags}`;
×
125
      }
126
    }
127
    if (node.bigint != null) {
66✔
128
      try {
2✔
129
        return BigInt(node.bigint);
2✔
130
      } catch {
131
        return `${node.bigint}`;
×
132
      }
133
    }
134
    return node.value;
64✔
135
  },
136
  JSONUnaryExpression(node: JSONUnaryExpression) {
137
    const value = getStaticJSONValue(node.argument);
18✔
138
    return node.operator === "-" ? -value : value;
18✔
139
  },
140
  JSONBinaryExpression(node: JSONBinaryExpression) {
141
    const left = getStaticJSONValue(node.left);
7✔
142
    const right = getStaticJSONValue(node.right);
7✔
143
    return node.operator === "+"
7✔
144
      ? left + right
145
      : node.operator === "-"
5✔
146
        ? left - right
147
        : node.operator === "*"
4✔
148
          ? left * right
149
          : node.operator === "/"
3✔
150
            ? left / right
151
            : node.operator === "%"
2✔
152
              ? left % right
153
              : node.operator === "**"
1!
154
                ? left ** right
155
                : (() => {
156
                    throw new Error(`Unknown operator: ${node.operator}`);
×
157
                  })();
158
  },
159
  JSONIdentifier(node: JSONIdentifier) {
160
    if (node.name === "Infinity") {
21✔
161
      return Infinity;
8✔
162
    }
163
    if (node.name === "NaN") {
13✔
164
      return NaN;
8✔
165
    }
166
    if (node.name === "undefined") {
5✔
167
      return undefined;
4✔
168
    }
169
    throw new Error("Illegal argument");
1✔
170
  },
171
  JSONTemplateLiteral(node: JSONTemplateLiteral) {
172
    return getStaticJSONValue(node.quasis[0]);
5✔
173
  },
174
  JSONTemplateElement(node: JSONTemplateElement) {
175
    return node.value.cooked;
5✔
176
  },
177
};
178

179
export function getStaticJSONValue(
180
  node:
181
    | JSONUnaryExpression
182
    | JSONNumberIdentifier
183
    | JSONNumberLiteral
184
    | JSONBinaryExpression,
185
): number;
186
export function getStaticJSONValue(node: JSONUndefinedIdentifier): undefined;
187
export function getStaticJSONValue(
188
  node: JSONTemplateLiteral | JSONTemplateElement | JSONStringLiteral,
189
): string;
190
export function getStaticJSONValue(node: JSONKeywordLiteral): boolean | null;
191
export function getStaticJSONValue(node: JSONRegExpLiteral): RegExp;
192
export function getStaticJSONValue(node: JSONBigIntLiteral): bigint;
193
export function getStaticJSONValue(
194
  node: JSONLiteral,
195
): string | number | boolean | RegExp | bigint | null;
196
export function getStaticJSONValue(
197
  node: Exclude<JSONExpression, JSONObjectExpression | JSONArrayExpression>,
198
): Exclude<JSONValue, JSONObjectValue | JSONValue[]>;
199

200
export function getStaticJSONValue(node: JSONObjectExpression): JSONObjectValue;
201
export function getStaticJSONValue(node: JSONArrayExpression): JSONValue[];
202
export function getStaticJSONValue(
203
  node: JSONExpression | JSONExpressionStatement | JSONProgram | JSONNode,
204
): JSONValue;
205

206
/**
207
 * Gets the static value for the given node.
208
 */
209
export function getStaticJSONValue(node: JSONNode): JSONValue {
1✔
210
  return resolver[node.type](node);
282✔
211
}
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

© 2025 Coveralls, Inc