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

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

04 Apr 2025 01:07AM UTC coverage: 87.338%. Remained the same
14255848708

Pull #371

github

web-flow
Merge 17d1eb549 into 327e06fbd
Pull Request #371: chore(deps): update dependency vue-eslint-parser to v10

372 of 455 branches covered (81.76%)

Branch coverage included in aggregate %.

911 of 1014 relevant lines covered (89.84%)

174.61 hits per line

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

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

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

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

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

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

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

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