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

ota-meshi / eslint-plugin-json-schema-validator / 21108009668

18 Jan 2026 07:22AM UTC coverage: 78.196% (-9.2%) from 87.363%
21108009668

Pull #452

github

web-flow
Merge dfb762a3b into bb8e97af5
Pull Request #452: Bundle using tsdown

717 of 872 branches covered (82.22%)

Branch coverage included in aggregate %.

30 of 51 new or added lines in 7 files covered. (58.82%)

574 existing lines in 11 files now uncovered.

2170 of 2820 relevant lines covered (76.95%)

55.12 hits per line

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

83.44
/src/utils/ast/json.ts
1
import type { AST as JSON } from "jsonc-eslint-parser";
1✔
2
import type { GetNodeFromPath, NodeData } from "./common";
1✔
3

1✔
4
type TraverseTarget =
1✔
5
  | JSON.JSONProgram
1✔
6
  | JSON.JSONExpressionStatement
1✔
7
  | JSON.JSONObjectExpression
1✔
8
  | JSON.JSONArrayExpression;
1✔
9

1✔
10
const TRAVERSE_TARGET_TYPE: Set<string> = new Set([
1✔
11
  "Program",
1✔
12
  "JSONExpressionStatement",
1✔
13
  "JSONObjectExpression",
1✔
14
  "JSONArrayExpression",
1✔
15
] as TraverseTarget["type"][]);
1✔
16

1✔
17
const GET_JSON_NODES: Record<
1✔
18
  TraverseTarget["type"],
1✔
19
  GetNodeFromPath<JSON.JSONNode>
1✔
20
> = {
1✔
21
  Program(node: JSON.JSONProgram, _paths: string[]) {
1✔
22
    return { value: node.body[0] };
120✔
23
  },
120✔
24
  JSONExpressionStatement(
1✔
25
    node: JSON.JSONExpressionStatement,
120✔
26
    _paths: string[],
120✔
27
  ) {
120✔
28
    return { value: node.expression };
120✔
29
  },
2✔
30
  JSONObjectExpression(node: JSON.JSONObjectExpression, paths: string[]) {
2✔
31
    const path = String(paths.shift());
173✔
32
    for (const prop of node.properties) {
1✔
33
      if (prop.key.type === "JSONIdentifier") {
1✔
34
        if (prop.key.name === path) {
7✔
35
          return { key: () => prop.key.range, value: prop.value };
1!
UNCOV
36
        }
×
UNCOV
37
      } else {
✔
38
        if (String(prop.key.value) === path) {
1✔
39
          return { key: () => prop.key.range, value: prop.value };
1✔
40
        }
1✔
41
      }
1✔
42
    }
1✔
43
    throw new Error(`${"Unexpected state: ["}${[path, ...paths].join(", ")}]`);
1!
44
  },
1✔
45
  JSONArrayExpression(node: JSON.JSONArrayExpression, paths: string[]) {
1✔
46
    const path = String(paths.shift());
57✔
47
    for (let index = 0; index < node.elements.length; index++) {
57✔
48
      if (String(index) !== path) {
104✔
49
        continue;
47✔
50
      }
47✔
51
      const element = node.elements[index];
104✔
UNCOV
52

×
53
      if (element) {
104✔
54
        return { value: element };
53✔
55
      }
53✔
56
      return {
104✔
57
        key: (sourceCode) => {
4✔
58
          const before = node.elements
4✔
59
            .slice(0, index)
4✔
60
            .reverse()
4✔
61
            .find((n) => n != null);
4✔
62
          let tokenIndex = before ? node.elements.indexOf(before) : -1;
4✔
63
          let token = before
4✔
UNCOV
64
            ? sourceCode.getTokenAfter(before)!
✔
65
            : sourceCode.getFirstToken(node);
1✔
UNCOV
66
          while (tokenIndex < index) {
✔
UNCOV
67
            tokenIndex++;
×
68
            token = sourceCode.getTokenAfter(token)!;
5✔
UNCOV
69
          }
×
UNCOV
70

×
UNCOV
71
          return [sourceCode.getTokenBefore(token)!.range![1], token.range![0]];
×
UNCOV
72
        },
×
UNCOV
73
        value: null,
×
UNCOV
74
      };
×
UNCOV
75
    }
×
76
    throw new Error(`${"Unexpected state: ["}${[path, ...paths].join(", ")}]`);
✔
UNCOV
77
  },
×
UNCOV
78
};
×
UNCOV
79
/**
×
UNCOV
80
 * Get node from path
×
UNCOV
81
 */
×
UNCOV
82
export function getJSONNodeFromPath(
✔
83
  node: JSON.JSONProgram,
134✔
84
  [...paths]: string[],
134✔
85
): NodeData<JSON.JSONNode> {
134✔
86
  let data: NodeData<JSON.JSONNode> = {
134✔
87
    key: (sourceCode) => {
134✔
88
      const dataNode = node.body[0].expression;
14✔
89
      if (
14✔
90
        dataNode.type === "JSONObjectExpression" ||
14✔
91
        dataNode.type === "JSONArrayExpression"
2✔
92
      ) {
14✔
93
        return sourceCode.getFirstToken(dataNode).range!;
12✔
94
      }
12✔
95
      return dataNode.range;
14✔
96
    },
14✔
97
    value: node,
134✔
98
  };
134✔
99
  while (paths.length && data.value) {
134✔
100
    if (!isTraverseTarget(data.value)) {
470!
101
      throw new Error(`Unexpected node type: ${data.value.type}`);
×
UNCOV
102
    }
×
103
    data = GET_JSON_NODES[data.value.type](data.value as never, paths);
470✔
104
  }
470✔
105
  return data;
134✔
106
}
134✔
107

1✔
108
/**
1✔
109
 * Checks whether given node is traverse target.
1✔
110
 */
1✔
111
function isTraverseTarget(node: JSON.JSONNode): node is TraverseTarget {
470✔
112
  return TRAVERSE_TARGET_TYPE.has(node.type);
470✔
113
}
470✔
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