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

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

07 Jun 2025 04:00PM CUT coverage: 87.33%. Remained the same
15509456335

Pull #371

github

web-flow
Merge 6eb844245 into 6fa634a04
Pull Request #371: chore(deps): update dependency vue-eslint-parser to v10

372 of 455 branches covered (81.76%)

Branch coverage included in aggregate %.

910 of 1013 relevant lines covered (89.83%)

178.84 hits per line

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

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

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

8
/**
9
 * Gets the property name of a given node.
10
 */
11
export function getStaticPropertyName(
12
  node: AST.ESLintProperty | AST.ESLintMemberExpression,
13
  context: RuleContext,
14
): string | null {
15
  let key;
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
      }
22
    }
23
  } else if (node.type === "MemberExpression") {
19!
24
    key = node.property;
19✔
25
    if (!node.computed) {
19✔
26
      if (key.type === "Identifier") {
15✔
27
        return key.name;
15✔
28
      }
29
      return null;
×
30
    }
31
  } else {
32
    return null;
×
33
  }
34
  if (key.type === "Literal" || key.type === "TemplateLiteral") {
76✔
35
    return getStringLiteralValue(key);
74✔
36
  }
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!
42
        init.node.type === "TemplateLiteral"
43
      ) {
44
        return getStringLiteralValue(init.node);
1✔
45
      }
46
    }
47
  }
48
  return null;
1✔
49
}
50

51
/**
52
 * Gets the string of a given node.
53
 */
54
export function getStringLiteralValue(
55
  node: AST.ESLintLiteral | AST.ESLintTemplateLiteral,
56
): string | null {
57
  if (node.type === "Literal") {
75✔
58
    if (node.value == null) {
74✔
59
      if (node.bigint != null) {
1!
60
        return String(node.bigint);
×
61
      }
62
    }
63
    return String(node.value);
74✔
64
  }
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
    }
69
  }
70
  return null;
×
71
}
72

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

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

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

128
      return {
74✔
129
        node: init,
130
        reads,
131
      };
132
    }
133
  }
134
  return null;
27✔
135
}
136

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

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

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

161
  return scopeManager.scopes[0];
×
162
}
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