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

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

18 Jan 2026 07:45AM UTC coverage: 89.746% (+2.4%) from 87.363%
21108266983

Pull #452

github

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

584 of 680 branches covered (85.88%)

Branch coverage included in aggregate %.

83 of 96 new or added lines in 15 files covered. (86.46%)

149 existing lines in 10 files now uncovered.

2558 of 2821 relevant lines covered (90.68%)

234.22 hits per line

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

87.92
/src/utils/ast/js/utils.ts
1
import * as eslintUtils from "@eslint-community/eslint-utils";
1✔
2
import type { Variable } from "eslint-scope";
1✔
3
import type { AST } from "vue-eslint-parser";
1✔
4

1✔
5
import type { RuleContext } from "../../../types.ts";
1✔
6
import { getSourceCode } from "../../compat.ts";
1✔
7

1✔
8
/**
1✔
9
 * Gets the property name of a given node.
1✔
10
 */
1✔
11
export function getStaticPropertyName(
1✔
12
  node: AST.ESLintProperty | AST.ESLintMemberExpression,
184✔
13
  context: RuleContext,
184✔
14
): string | null {
184✔
15
  let key;
184✔
16
  if (node.type === "Property") {
184✔
17
    key = node.key;
165✔
18
    if (!node.computed) {
165✔
19
      if (key.type === "Identifier") {
160✔
20
        return key.name;
93✔
21
      }
93✔
22
    }
160✔
23
  } else if (node.type === "MemberExpression") {
184✔
24
    key = node.property;
19✔
25
    if (!node.computed) {
19✔
26
      if (key.type === "Identifier") {
15✔
27
        return key.name;
15✔
28
      }
15!
29
      return null;
×
UNCOV
30
    }
×
31
  } else {
19!
32
    return null;
×
UNCOV
33
  }
✔
34
  if (key.type === "Literal" || key.type === "TemplateLiteral") {
184✔
35
    return getStringLiteralValue(key);
74✔
36
  }
74✔
37
  if (key.type === "Identifier") {
2✔
38
    const init = findInitNode(context, key);
2✔
39
    if (init) {
2✔
40
      if (
1✔
41
        init.node.type === "Literal" ||
1!
UNCOV
42
        init.node.type === "TemplateLiteral"
×
43
      ) {
1✔
44
        return getStringLiteralValue(init.node);
1✔
45
      }
1✔
46
    }
1✔
47
  }
2✔
48
  return null;
1✔
49
}
1✔
50

1✔
51
/**
1✔
52
 * Gets the string of a given node.
1✔
53
 */
1✔
54
export function getStringLiteralValue(
1✔
55
  node: AST.ESLintLiteral | AST.ESLintTemplateLiteral,
75✔
56
): string | null {
75✔
57
  if (node.type === "Literal") {
75✔
58
    if (node.value == null) {
74✔
59
      if (node.bigint != null) {
1!
60
        return String(node.bigint);
×
UNCOV
61
      }
×
62
    }
1✔
63
    return String(node.value);
74✔
64
  }
74✔
65
  if (node.type === "TemplateLiteral") {
1✔
66
    if (node.expressions.length === 0 && node.quasis.length === 1) {
1✔
67
      return node.quasis[0].value.cooked;
1✔
68
    }
1✔
69
  }
1!
70
  return null;
×
UNCOV
71
}
×
72

1✔
73
/**
1✔
74
 * Find the variable of a given name.
1✔
75
 */
1✔
76
function findVariable(
103✔
77
  context: RuleContext,
103✔
78
  node: AST.ESLintIdentifier,
103✔
79
): Variable | null {
103✔
80
  return eslintUtils.findVariable(
103✔
81
    getScope(context, node),
103✔
82
    node,
103✔
83
  ) as Variable | null;
103✔
84
}
103✔
85

1✔
86
/**
1✔
87
 * Get the value of a given node if it's a static value.
1✔
88
 */
1✔
89
export function getStaticValue(
1✔
90
  context: RuleContext,
31✔
91
  node: AST.ESLintNode,
31✔
92
): { value?: unknown; optional?: boolean } | null {
31✔
93
  return eslintUtils.getStaticValue(
31✔
94
    // @ts-expect-error -- `eslintUtils` is typed now but incompatible with Vue AST typings
31✔
95
    node,
31✔
96
    getScope(context, node),
31✔
97
  );
31✔
98
}
31✔
99

1✔
100
/**
1✔
101
 * Find the node that initial value.
1✔
102
 */
1✔
103
export function findInitNode(
1✔
104
  context: RuleContext,
103✔
105
  node: AST.ESLintIdentifier,
103✔
106
): { node: AST.ESLintExpression; reads: AST.ESLintIdentifier[] } | null {
103✔
107
  const variable = findVariable(context, node);
103✔
108
  if (!variable) {
103!
109
    return null;
×
UNCOV
110
  }
×
111
  if (variable.defs.length === 1) {
103✔
112
    const def = variable.defs[0];
96✔
113
    if (
96✔
114
      def.type === "Variable" &&
96✔
115
      def.parent.kind === "const" &&
95✔
116
      def.node.init
76✔
117
    ) {
96✔
118
      let init = def.node.init as AST.ESLintExpression;
76✔
119
      const reads = variable.references
76✔
120
        .filter((ref) => ref.isRead())
76✔
121
        .map((ref) => ref.identifier as AST.ESLintIdentifier);
76✔
122
      if (init.type === "Identifier") {
76✔
123
        const data = findInitNode(context, init);
3✔
124
        if (!data) {
3✔
125
          return null;
2✔
126
        }
2✔
127
        init = data.node;
1✔
128
        reads.push(...data.reads);
1✔
129
      }
1✔
130

74✔
131
      return {
74✔
132
        node: init,
74✔
133
        reads,
74✔
134
      };
74✔
135
    }
74✔
136
  }
96✔
137
  return null;
27✔
138
}
27✔
139

1✔
140
/**
1✔
141
 * Gets the scope for the current node
1✔
142
 */
1✔
143
function getScope(context: RuleContext, currentNode: AST.ESLintNode) {
134✔
144
  // On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
134✔
145
  const inner = currentNode.type !== "Program";
134✔
146
  const scopeManager = getSourceCode(context).scopeManager;
134✔
147

134✔
148
  let node: AST.Node | null = currentNode;
134✔
149
  for (; node; node = node.parent || null) {
134!
150
    const scope = scopeManager.acquire(
744✔
151
      // @ts-expect-error -- incompatible with Vue AST typings
744✔
152
      node,
744✔
153
      inner,
744✔
154
    );
744✔
155

744✔
156
    if (scope) {
744✔
157
      if (scope.type === "function-expression-name") {
134!
158
        return scope.childScopes[0];
×
UNCOV
159
      }
×
160
      return scope;
134✔
161
    }
134✔
162
  }
744!
UNCOV
163

×
164
  return scopeManager.scopes[0];
×
UNCOV
165
}
×
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