WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
import type { TSESLint } from '@typescript-eslint/utils';
|
||||
export type Options = ['fields' | 'getters'];
|
||||
export type MessageIds = 'preferFieldStyle' | 'preferFieldStyleSuggestion' | 'preferGetterStyle' | 'preferGetterStyleSuggestion';
|
||||
declare const _default: TSESLint.RuleModule<MessageIds, Options, import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
import { getCurrentSuite } from '@vitest/runner';
|
||||
import { createChainable } from '@vitest/runner/utils';
|
||||
import { noop } from '@vitest/utils/helpers';
|
||||
import { g as getWorkerState } from './utils.BX5Fg8C4.js';
|
||||
|
||||
const benchFns = /* @__PURE__ */ new WeakMap();
|
||||
const benchOptsMap = /* @__PURE__ */ new WeakMap();
|
||||
function getBenchOptions(key) {
|
||||
return benchOptsMap.get(key);
|
||||
}
|
||||
function getBenchFn(key) {
|
||||
return benchFns.get(key);
|
||||
}
|
||||
const bench = createBenchmark(function(name, fn = noop, options = {}) {
|
||||
if (getWorkerState().config.mode !== "benchmark") throw new Error("`bench()` is only available in benchmark mode.");
|
||||
const task = getCurrentSuite().task(formatName(name), {
|
||||
...this,
|
||||
meta: { benchmark: true }
|
||||
});
|
||||
benchFns.set(task, fn);
|
||||
benchOptsMap.set(task, options);
|
||||
// vitest runner sets mode to `todo` if handler is not passed down
|
||||
// but we store handler separately
|
||||
if (!this.todo && task.mode === "todo") task.mode = "run";
|
||||
});
|
||||
function createBenchmark(fn) {
|
||||
const benchmark = createChainable([
|
||||
"skip",
|
||||
"only",
|
||||
"todo"
|
||||
], fn);
|
||||
benchmark.skipIf = (condition) => condition ? benchmark.skip : benchmark;
|
||||
benchmark.runIf = (condition) => condition ? benchmark : benchmark.skip;
|
||||
return benchmark;
|
||||
}
|
||||
function formatName(name) {
|
||||
return typeof name === "string" ? name : typeof name === "function" ? name.name || "<anonymous>" : String(name);
|
||||
}
|
||||
|
||||
export { getBenchOptions as a, bench as b, getBenchFn as g };
|
||||
@@ -0,0 +1,3 @@
|
||||
# Oxc Types
|
||||
|
||||
Typescript definitions for Oxc AST nodes.
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @fileoverview Default configuration
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const Rules = require("../rules");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const sharedDefaultConfig = [
|
||||
// intentionally empty config to ensure these files are globbed by default
|
||||
{
|
||||
files: ["**/*.js", "**/*.mjs"],
|
||||
},
|
||||
{
|
||||
files: ["**/*.cjs"],
|
||||
languageOptions: {
|
||||
sourceType: "commonjs",
|
||||
ecmaVersion: "latest",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
exports.defaultConfig = Object.freeze([
|
||||
{
|
||||
plugins: {
|
||||
"@": {
|
||||
languages: {
|
||||
js: require("../languages/js"),
|
||||
},
|
||||
|
||||
/*
|
||||
* Because we try to delay loading rules until absolutely
|
||||
* necessary, a proxy allows us to hook into the lazy-loading
|
||||
* aspect of the rules map while still keeping all of the
|
||||
* relevant configuration inside of the config array.
|
||||
*/
|
||||
rules: new Proxy(
|
||||
{},
|
||||
{
|
||||
get(target, property) {
|
||||
return Rules.get(property);
|
||||
},
|
||||
|
||||
has(target, property) {
|
||||
return Rules.has(property);
|
||||
},
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
language: "@/js",
|
||||
linterOptions: {
|
||||
reportUnusedDisableDirectives: 1,
|
||||
},
|
||||
},
|
||||
|
||||
// default ignores are listed here
|
||||
{
|
||||
ignores: ["**/node_modules/", ".git/"],
|
||||
},
|
||||
|
||||
...sharedDefaultConfig,
|
||||
]);
|
||||
|
||||
exports.defaultRuleTesterConfig = Object.freeze([
|
||||
{ files: ["**"] }, // Make sure the default config matches for all files
|
||||
|
||||
...sharedDefaultConfig,
|
||||
]);
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { TSESLint } from '@typescript-eslint/utils';
|
||||
export type MessageIds = 'noEnumShadow' | 'noShadow' | 'noShadowGlobal';
|
||||
export type Options = [
|
||||
{
|
||||
allow?: string[];
|
||||
builtinGlobals?: boolean;
|
||||
hoist?: 'all' | 'functions' | 'functions-and-types' | 'never' | 'types';
|
||||
ignoreFunctionTypeParameterNameValueShadow?: boolean;
|
||||
ignoreOnInitialization?: boolean;
|
||||
ignoreTypeValueShadow?: boolean;
|
||||
}
|
||||
];
|
||||
declare const _default: TSESLint.RuleModule<MessageIds, Options, import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,73 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = prettifyErrorLog
|
||||
|
||||
const {
|
||||
LOGGER_KEYS
|
||||
} = require('../constants')
|
||||
|
||||
const isObject = require('./is-object')
|
||||
const joinLinesWithIndentation = require('./join-lines-with-indentation')
|
||||
const prettifyObject = require('./prettify-object')
|
||||
|
||||
/**
|
||||
* @typedef {object} PrettifyErrorLogParams
|
||||
* @property {object} log The error log to prettify.
|
||||
* @property {PrettyContext} context The context object built from parsing
|
||||
* the options.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Given a log object that has a `type: 'Error'` key, prettify the object and
|
||||
* return the result. In other
|
||||
*
|
||||
* @param {PrettifyErrorLogParams} input
|
||||
*
|
||||
* @returns {string} A string that represents the prettified error log.
|
||||
*/
|
||||
function prettifyErrorLog ({ log, context }) {
|
||||
const {
|
||||
EOL: eol,
|
||||
IDENT: ident,
|
||||
errorProps: errorProperties,
|
||||
messageKey
|
||||
} = context
|
||||
const stack = log.stack
|
||||
const joinedLines = joinLinesWithIndentation({ input: stack, ident, eol })
|
||||
let result = `${ident}${joinedLines}${eol}`
|
||||
|
||||
if (errorProperties.length > 0) {
|
||||
const excludeProperties = LOGGER_KEYS.concat(messageKey, 'type', 'stack')
|
||||
let propertiesToPrint
|
||||
if (errorProperties[0] === '*') {
|
||||
// Print all sibling properties except for the standard exclusions.
|
||||
propertiesToPrint = Object.keys(log).filter(k => excludeProperties.includes(k) === false)
|
||||
} else {
|
||||
// Print only specified properties unless the property is a standard exclusion.
|
||||
propertiesToPrint = errorProperties.filter(k => excludeProperties.includes(k) === false)
|
||||
}
|
||||
|
||||
for (let i = 0; i < propertiesToPrint.length; i += 1) {
|
||||
const key = propertiesToPrint[i]
|
||||
if (key in log === false) continue
|
||||
if (isObject(log[key])) {
|
||||
// The nested object may have "logger" type keys but since they are not
|
||||
// at the root level of the object being processed, we want to print them.
|
||||
// Thus, we invoke with `excludeLoggerKeys: false`.
|
||||
const prettifiedObject = prettifyObject({
|
||||
log: log[key],
|
||||
excludeLoggerKeys: false,
|
||||
context: {
|
||||
...context,
|
||||
IDENT: ident + ident
|
||||
}
|
||||
})
|
||||
result = `${result}${ident}${key}: {${eol}${prettifiedObject}${ident}}${eol}`
|
||||
continue
|
||||
}
|
||||
result = `${result}${ident}${key}: ${log[key]}${eol}`
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// RUN THE FOLLOWING COMMAND FROM THE WORKSPACE ROOT TO REGENERATE:
|
||||
// npx nx generate-lib repo
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.es2019_intl = void 0;
|
||||
const base_config_1 = require("./base-config");
|
||||
exports.es2019_intl = {
|
||||
libs: [],
|
||||
variables: [['Intl', base_config_1.TYPE_VALUE]],
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = default_1;
|
||||
const util = __importStar(require("../core/util.cjs"));
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: { unit: "знаци", verb: "да имаат" },
|
||||
file: { unit: "бајти", verb: "да имаат" },
|
||||
array: { unit: "ставки", verb: "да имаат" },
|
||||
set: { unit: "ставки", verb: "да имаат" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "внес",
|
||||
email: "адреса на е-пошта",
|
||||
url: "URL",
|
||||
emoji: "емоџи",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO датум и време",
|
||||
date: "ISO датум",
|
||||
time: "ISO време",
|
||||
duration: "ISO времетраење",
|
||||
ipv4: "IPv4 адреса",
|
||||
ipv6: "IPv6 адреса",
|
||||
cidrv4: "IPv4 опсег",
|
||||
cidrv6: "IPv6 опсег",
|
||||
base64: "base64-енкодирана низа",
|
||||
base64url: "base64url-енкодирана низа",
|
||||
json_string: "JSON низа",
|
||||
e164: "E.164 број",
|
||||
jwt: "JWT",
|
||||
template_literal: "внес",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
number: "број",
|
||||
array: "низа",
|
||||
};
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
const expected = TypeDictionary[issue.expected] ?? issue.expected;
|
||||
const receivedType = util.parsedType(issue.input);
|
||||
const received = TypeDictionary[receivedType] ?? receivedType;
|
||||
if (/^[A-Z]/.test(issue.expected)) {
|
||||
return `Грешен внес: се очекува instanceof ${issue.expected}, примено ${received}`;
|
||||
}
|
||||
return `Грешен внес: се очекува ${expected}, примено ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Invalid input: expected ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Грешана опција: се очекува една ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Премногу голем: се очекува ${issue.origin ?? "вредноста"} да има ${adj}${issue.maximum.toString()} ${sizing.unit ?? "елементи"}`;
|
||||
return `Премногу голем: се очекува ${issue.origin ?? "вредноста"} да биде ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Премногу мал: се очекува ${issue.origin} да има ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `Премногу мал: се очекува ${issue.origin} да биде ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with") {
|
||||
return `Неважечка низа: мора да започнува со "${_issue.prefix}"`;
|
||||
}
|
||||
if (_issue.format === "ends_with")
|
||||
return `Неважечка низа: мора да завршува со "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Неважечка низа: мора да вклучува "${_issue.includes}"`;
|
||||
if (_issue.format === "regex")
|
||||
return `Неважечка низа: мора да одгоара на патернот ${_issue.pattern}`;
|
||||
return `Invalid ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Грешен број: мора да биде делив со ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `${issue.keys.length > 1 ? "Непрепознаени клучеви" : "Непрепознаен клуч"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Грешен клуч во ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Грешен внес";
|
||||
case "invalid_element":
|
||||
return `Грешна вредност во ${issue.origin}`;
|
||||
default:
|
||||
return `Грешен внес`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1,17 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
import ts = require("./typescript.js");
|
||||
export = ts;
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const debug = (
|
||||
typeof process === 'object' &&
|
||||
process.env &&
|
||||
process.env.NODE_DEBUG &&
|
||||
/\bsemver\b/i.test(process.env.NODE_DEBUG)
|
||||
) ? (...args) => console.error('SEMVER', ...args)
|
||||
: () => {}
|
||||
|
||||
module.exports = debug
|
||||
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow Math.pow in favor of the ** operator
|
||||
* @author Milos Djermanovic
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
const { CALL, ReferenceTracker } = require("@eslint-community/eslint-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const PRECEDENCE_OF_EXPONENTIATION_EXPR = astUtils.getPrecedence({
|
||||
type: "BinaryExpression",
|
||||
operator: "**",
|
||||
});
|
||||
|
||||
/*
|
||||
* Characters that can cause continuation without preceding semi
|
||||
*/
|
||||
const continuationChars = new Set(["(", "[", "/", "`"]);
|
||||
|
||||
/**
|
||||
* Determines whether the given node needs parens if used as the base in an exponentiation binary expression.
|
||||
* @param {ASTNode} base The node to check.
|
||||
* @returns {boolean} `true` if the node needs to be parenthesised.
|
||||
*/
|
||||
function doesBaseNeedParens(base) {
|
||||
return (
|
||||
// '**' is right-associative, parens are needed when Math.pow(a ** b, c) is converted to (a ** b) ** c
|
||||
astUtils.getPrecedence(base) <= PRECEDENCE_OF_EXPONENTIATION_EXPR ||
|
||||
// An unary operator cannot be used immediately before an exponentiation expression
|
||||
base.type === "AwaitExpression" ||
|
||||
base.type === "UnaryExpression"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given node needs parens if used as the exponent in an exponentiation binary expression.
|
||||
* @param {ASTNode} exponent The node to check.
|
||||
* @returns {boolean} `true` if the node needs to be parenthesised.
|
||||
*/
|
||||
function doesExponentNeedParens(exponent) {
|
||||
// '**' is right-associative, there is no need for parens when Math.pow(a, b ** c) is converted to a ** b ** c
|
||||
return astUtils.getPrecedence(exponent) < PRECEDENCE_OF_EXPONENTIATION_EXPR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an exponentiation binary expression at the place of the given node would need parens.
|
||||
* @param {ASTNode} node A node that would be replaced by an exponentiation binary expression.
|
||||
* @param {SourceCode} sourceCode A SourceCode object.
|
||||
* @returns {boolean} `true` if the expression needs to be parenthesised.
|
||||
*/
|
||||
function doesExponentiationExpressionNeedParens(node, sourceCode) {
|
||||
const parent =
|
||||
node.parent.type === "ChainExpression"
|
||||
? node.parent.parent
|
||||
: node.parent;
|
||||
|
||||
const parentPrecedence = astUtils.getPrecedence(parent);
|
||||
const needsParens =
|
||||
parent.type === "ClassDeclaration" ||
|
||||
(parent.type.endsWith("Expression") &&
|
||||
(parentPrecedence === -1 ||
|
||||
parentPrecedence >= PRECEDENCE_OF_EXPONENTIATION_EXPR) &&
|
||||
!(
|
||||
parent.type === "BinaryExpression" &&
|
||||
parent.operator === "**" &&
|
||||
parent.right === node
|
||||
) &&
|
||||
!(
|
||||
(parent.type === "CallExpression" ||
|
||||
parent.type === "NewExpression") &&
|
||||
parent.arguments.includes(node)
|
||||
) &&
|
||||
!(
|
||||
parent.type === "MemberExpression" &&
|
||||
parent.computed &&
|
||||
parent.property === node
|
||||
) &&
|
||||
!(parent.type === "ArrayExpression"));
|
||||
|
||||
return needsParens && !astUtils.isParenthesised(sourceCode, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally parenthesizes given text.
|
||||
* @param {string} text The text to parenthesize.
|
||||
* @param {boolean} shouldParenthesize If `true`, the text will be parenthesised.
|
||||
* @returns {string} parenthesised or unchanged text.
|
||||
*/
|
||||
function parenthesizeIfShould(text, shouldParenthesize) {
|
||||
return shouldParenthesize ? `(${text})` : text;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow the use of `Math.pow` in favor of the `**` operator",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/prefer-exponentiation-operator",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
fixable: "code",
|
||||
|
||||
messages: {
|
||||
useExponentiation: "Use the '**' operator instead of 'Math.pow'.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Reports the given node.
|
||||
* @param {ASTNode} node 'Math.pow()' node to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(node) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "useExponentiation",
|
||||
fix(fixer) {
|
||||
if (
|
||||
node.arguments.length !== 2 ||
|
||||
node.arguments.some(
|
||||
arg => arg.type === "SpreadElement",
|
||||
) ||
|
||||
sourceCode.getCommentsInside(node).length > 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const base = node.arguments[0],
|
||||
exponent = node.arguments[1],
|
||||
baseText = sourceCode.getText(base),
|
||||
exponentText = sourceCode.getText(exponent),
|
||||
shouldParenthesizeBase = doesBaseNeedParens(base),
|
||||
shouldParenthesizeExponent =
|
||||
doesExponentNeedParens(exponent),
|
||||
isStartOfExpressionStatement =
|
||||
astUtils.isStartOfExpressionStatement(node);
|
||||
|
||||
let shouldParenthesizeAll =
|
||||
doesExponentiationExpressionNeedParens(
|
||||
node,
|
||||
sourceCode,
|
||||
);
|
||||
|
||||
/*
|
||||
* `function`, `class`, or `{` token at the start of an expression statement
|
||||
* would cause incorrect parsing.
|
||||
* https://github.com/eslint/eslint/issues/20987
|
||||
*/
|
||||
if (
|
||||
!shouldParenthesizeAll &&
|
||||
!shouldParenthesizeBase &&
|
||||
isStartOfExpressionStatement
|
||||
) {
|
||||
const firstTokenOfBase = sourceCode.getFirstToken(base);
|
||||
|
||||
if (
|
||||
astUtils.isOpeningBraceToken(firstTokenOfBase) ||
|
||||
(firstTokenOfBase.type === "Keyword" &&
|
||||
(firstTokenOfBase.value === "function" ||
|
||||
firstTokenOfBase.value === "class"))
|
||||
) {
|
||||
shouldParenthesizeAll = true;
|
||||
}
|
||||
}
|
||||
|
||||
let prefix = "",
|
||||
suffix = "";
|
||||
|
||||
if (!shouldParenthesizeAll) {
|
||||
if (!shouldParenthesizeBase) {
|
||||
const firstReplacementToken =
|
||||
sourceCode.getFirstToken(base),
|
||||
tokenBefore = sourceCode.getTokenBefore(node);
|
||||
|
||||
if (
|
||||
tokenBefore &&
|
||||
tokenBefore.range[1] === node.range[0] &&
|
||||
!astUtils.canTokensBeAdjacent(
|
||||
tokenBefore,
|
||||
firstReplacementToken,
|
||||
)
|
||||
) {
|
||||
prefix = " "; // a+Math.pow(++b, c) -> a+ ++b**c
|
||||
}
|
||||
}
|
||||
if (!shouldParenthesizeExponent) {
|
||||
const lastReplacementToken =
|
||||
sourceCode.getLastToken(exponent),
|
||||
tokenAfter = sourceCode.getTokenAfter(node);
|
||||
|
||||
if (
|
||||
tokenAfter &&
|
||||
node.range[1] === tokenAfter.range[0] &&
|
||||
!astUtils.canTokensBeAdjacent(
|
||||
lastReplacementToken,
|
||||
tokenAfter,
|
||||
)
|
||||
) {
|
||||
suffix = " "; // Math.pow(a, b)in c -> a**b in c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const baseReplacement = parenthesizeIfShould(
|
||||
baseText,
|
||||
shouldParenthesizeBase,
|
||||
),
|
||||
exponentReplacement = parenthesizeIfShould(
|
||||
exponentText,
|
||||
shouldParenthesizeExponent,
|
||||
),
|
||||
replacement = parenthesizeIfShould(
|
||||
`${baseReplacement}**${exponentReplacement}`,
|
||||
shouldParenthesizeAll,
|
||||
);
|
||||
|
||||
if (
|
||||
!prefix &&
|
||||
isStartOfExpressionStatement &&
|
||||
continuationChars.has(replacement[0]) &&
|
||||
astUtils.needsPrecedingSemicolon(sourceCode, node)
|
||||
) {
|
||||
prefix = ";";
|
||||
}
|
||||
|
||||
return fixer.replaceText(
|
||||
node,
|
||||
`${prefix}${replacement}${suffix}`,
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
const scope = sourceCode.getScope(node);
|
||||
const tracker = new ReferenceTracker(scope);
|
||||
const trackMap = {
|
||||
Math: {
|
||||
pow: { [CALL]: true },
|
||||
},
|
||||
};
|
||||
|
||||
for (const { node: refNode } of tracker.iterateGlobalReferences(
|
||||
trackMap,
|
||||
)) {
|
||||
report(refNode);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,636 @@
|
||||
// A simple implementation of make-array
|
||||
function makeArray (subject) {
|
||||
return Array.isArray(subject)
|
||||
? subject
|
||||
: [subject]
|
||||
}
|
||||
|
||||
const EMPTY = ''
|
||||
const SPACE = ' '
|
||||
const ESCAPE = '\\'
|
||||
const REGEX_TEST_BLANK_LINE = /^\s+$/
|
||||
const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/
|
||||
const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/
|
||||
const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/
|
||||
const REGEX_SPLITALL_CRLF = /\r?\n/g
|
||||
// /foo,
|
||||
// ./foo,
|
||||
// ../foo,
|
||||
// .
|
||||
// ..
|
||||
const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/
|
||||
|
||||
const SLASH = '/'
|
||||
|
||||
// Do not use ternary expression here, since "istanbul ignore next" is buggy
|
||||
let TMP_KEY_IGNORE = 'node-ignore'
|
||||
/* istanbul ignore else */
|
||||
if (typeof Symbol !== 'undefined') {
|
||||
TMP_KEY_IGNORE = Symbol.for('node-ignore')
|
||||
}
|
||||
const KEY_IGNORE = TMP_KEY_IGNORE
|
||||
|
||||
const define = (object, key, value) =>
|
||||
Object.defineProperty(object, key, {value})
|
||||
|
||||
const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g
|
||||
|
||||
const RETURN_FALSE = () => false
|
||||
|
||||
// Sanitize the range of a regular expression
|
||||
// The cases are complicated, see test cases for details
|
||||
const sanitizeRange = range => range.replace(
|
||||
REGEX_REGEXP_RANGE,
|
||||
(match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)
|
||||
? match
|
||||
// Invalid range (out of order) which is ok for gitignore rules but
|
||||
// fatal for JavaScript regular expression, so eliminate it.
|
||||
: EMPTY
|
||||
)
|
||||
|
||||
// See fixtures #59
|
||||
const cleanRangeBackSlash = slashes => {
|
||||
const {length} = slashes
|
||||
return slashes.slice(0, length - length % 2)
|
||||
}
|
||||
|
||||
// > If the pattern ends with a slash,
|
||||
// > it is removed for the purpose of the following description,
|
||||
// > but it would only find a match with a directory.
|
||||
// > In other words, foo/ will match a directory foo and paths underneath it,
|
||||
// > but will not match a regular file or a symbolic link foo
|
||||
// > (this is consistent with the way how pathspec works in general in Git).
|
||||
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
|
||||
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
|
||||
// you could use option `mark: true` with `glob`
|
||||
|
||||
// '`foo/`' should not continue with the '`..`'
|
||||
const REPLACERS = [
|
||||
|
||||
[
|
||||
// remove BOM
|
||||
// TODO:
|
||||
// Other similar zero-width characters?
|
||||
/^\uFEFF/,
|
||||
() => EMPTY
|
||||
],
|
||||
|
||||
// > Trailing spaces are ignored unless they are quoted with backslash ("\")
|
||||
[
|
||||
// (a\ ) -> (a )
|
||||
// (a ) -> (a)
|
||||
// (a ) -> (a)
|
||||
// (a \ ) -> (a )
|
||||
/((?:\\\\)*?)(\\?\s+)$/,
|
||||
(_, m1, m2) => m1 + (
|
||||
m2.indexOf('\\') === 0
|
||||
? SPACE
|
||||
: EMPTY
|
||||
)
|
||||
],
|
||||
|
||||
// replace (\ ) with ' '
|
||||
// (\ ) -> ' '
|
||||
// (\\ ) -> '\\ '
|
||||
// (\\\ ) -> '\\ '
|
||||
[
|
||||
/(\\+?)\s/g,
|
||||
(_, m1) => {
|
||||
const {length} = m1
|
||||
return m1.slice(0, length - length % 2) + SPACE
|
||||
}
|
||||
],
|
||||
|
||||
// Escape metacharacters
|
||||
// which is written down by users but means special for regular expressions.
|
||||
|
||||
// > There are 12 characters with special meanings:
|
||||
// > - the backslash \,
|
||||
// > - the caret ^,
|
||||
// > - the dollar sign $,
|
||||
// > - the period or dot .,
|
||||
// > - the vertical bar or pipe symbol |,
|
||||
// > - the question mark ?,
|
||||
// > - the asterisk or star *,
|
||||
// > - the plus sign +,
|
||||
// > - the opening parenthesis (,
|
||||
// > - the closing parenthesis ),
|
||||
// > - and the opening square bracket [,
|
||||
// > - the opening curly brace {,
|
||||
// > These special characters are often called "metacharacters".
|
||||
[
|
||||
/[\\$.|*+(){^]/g,
|
||||
match => `\\${match}`
|
||||
],
|
||||
|
||||
[
|
||||
// > a question mark (?) matches a single character
|
||||
/(?!\\)\?/g,
|
||||
() => '[^/]'
|
||||
],
|
||||
|
||||
// leading slash
|
||||
[
|
||||
|
||||
// > A leading slash matches the beginning of the pathname.
|
||||
// > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
|
||||
// A leading slash matches the beginning of the pathname
|
||||
/^\//,
|
||||
() => '^'
|
||||
],
|
||||
|
||||
// replace special metacharacter slash after the leading slash
|
||||
[
|
||||
/\//g,
|
||||
() => '\\/'
|
||||
],
|
||||
|
||||
[
|
||||
// > A leading "**" followed by a slash means match in all directories.
|
||||
// > For example, "**/foo" matches file or directory "foo" anywhere,
|
||||
// > the same as pattern "foo".
|
||||
// > "**/foo/bar" matches file or directory "bar" anywhere that is directly
|
||||
// > under directory "foo".
|
||||
// Notice that the '*'s have been replaced as '\\*'
|
||||
/^\^*\\\*\\\*\\\//,
|
||||
|
||||
// '**/foo' <-> 'foo'
|
||||
() => '^(?:.*\\/)?'
|
||||
],
|
||||
|
||||
// starting
|
||||
[
|
||||
// there will be no leading '/'
|
||||
// (which has been replaced by section "leading slash")
|
||||
// If starts with '**', adding a '^' to the regular expression also works
|
||||
/^(?=[^^])/,
|
||||
function startingReplacer () {
|
||||
// If has a slash `/` at the beginning or middle
|
||||
return !/\/(?!$)/.test(this)
|
||||
// > Prior to 2.22.1
|
||||
// > If the pattern does not contain a slash /,
|
||||
// > Git treats it as a shell glob pattern
|
||||
// Actually, if there is only a trailing slash,
|
||||
// git also treats it as a shell glob pattern
|
||||
|
||||
// After 2.22.1 (compatible but clearer)
|
||||
// > If there is a separator at the beginning or middle (or both)
|
||||
// > of the pattern, then the pattern is relative to the directory
|
||||
// > level of the particular .gitignore file itself.
|
||||
// > Otherwise the pattern may also match at any level below
|
||||
// > the .gitignore level.
|
||||
? '(?:^|\\/)'
|
||||
|
||||
// > Otherwise, Git treats the pattern as a shell glob suitable for
|
||||
// > consumption by fnmatch(3)
|
||||
: '^'
|
||||
}
|
||||
],
|
||||
|
||||
// two globstars
|
||||
[
|
||||
// Use lookahead assertions so that we could match more than one `'/**'`
|
||||
/\\\/\\\*\\\*(?=\\\/|$)/g,
|
||||
|
||||
// Zero, one or several directories
|
||||
// should not use '*', or it will be replaced by the next replacer
|
||||
|
||||
// Check if it is not the last `'/**'`
|
||||
(_, index, str) => index + 6 < str.length
|
||||
|
||||
// case: /**/
|
||||
// > A slash followed by two consecutive asterisks then a slash matches
|
||||
// > zero or more directories.
|
||||
// > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
|
||||
// '/**/'
|
||||
? '(?:\\/[^\\/]+)*'
|
||||
|
||||
// case: /**
|
||||
// > A trailing `"/**"` matches everything inside.
|
||||
|
||||
// #21: everything inside but it should not include the current folder
|
||||
: '\\/.+'
|
||||
],
|
||||
|
||||
// normal intermediate wildcards
|
||||
[
|
||||
// Never replace escaped '*'
|
||||
// ignore rule '\*' will match the path '*'
|
||||
|
||||
// 'abc.*/' -> go
|
||||
// 'abc.*' -> skip this rule,
|
||||
// coz trailing single wildcard will be handed by [trailing wildcard]
|
||||
/(^|[^\\]+)(\\\*)+(?=.+)/g,
|
||||
|
||||
// '*.js' matches '.js'
|
||||
// '*.js' doesn't match 'abc'
|
||||
(_, p1, p2) => {
|
||||
// 1.
|
||||
// > An asterisk "*" matches anything except a slash.
|
||||
// 2.
|
||||
// > Other consecutive asterisks are considered regular asterisks
|
||||
// > and will match according to the previous rules.
|
||||
const unescaped = p2.replace(/\\\*/g, '[^\\/]*')
|
||||
return p1 + unescaped
|
||||
}
|
||||
],
|
||||
|
||||
[
|
||||
// unescape, revert step 3 except for back slash
|
||||
// For example, if a user escape a '\\*',
|
||||
// after step 3, the result will be '\\\\\\*'
|
||||
/\\\\\\(?=[$.|*+(){^])/g,
|
||||
() => ESCAPE
|
||||
],
|
||||
|
||||
[
|
||||
// '\\\\' -> '\\'
|
||||
/\\\\/g,
|
||||
() => ESCAPE
|
||||
],
|
||||
|
||||
[
|
||||
// > The range notation, e.g. [a-zA-Z],
|
||||
// > can be used to match one of the characters in a range.
|
||||
|
||||
// `\` is escaped by step 3
|
||||
/(\\)?\[([^\]/]*?)(\\*)($|\])/g,
|
||||
(match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE
|
||||
// '\\[bar]' -> '\\\\[bar\\]'
|
||||
? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`
|
||||
: close === ']'
|
||||
? endEscape.length % 2 === 0
|
||||
// A normal case, and it is a range notation
|
||||
// '[bar]'
|
||||
// '[bar\\\\]'
|
||||
? `[${sanitizeRange(range)}${endEscape}]`
|
||||
// Invalid range notaton
|
||||
// '[bar\\]' -> '[bar\\\\]'
|
||||
: '[]'
|
||||
: '[]'
|
||||
],
|
||||
|
||||
// ending
|
||||
[
|
||||
// 'js' will not match 'js.'
|
||||
// 'ab' will not match 'abc'
|
||||
/(?:[^*])$/,
|
||||
|
||||
// WTF!
|
||||
// https://git-scm.com/docs/gitignore
|
||||
// changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
|
||||
// which re-fixes #24, #38
|
||||
|
||||
// > If there is a separator at the end of the pattern then the pattern
|
||||
// > will only match directories, otherwise the pattern can match both
|
||||
// > files and directories.
|
||||
|
||||
// 'js*' will not match 'a.js'
|
||||
// 'js/' will not match 'a.js'
|
||||
// 'js' will match 'a.js' and 'a.js/'
|
||||
match => /\/$/.test(match)
|
||||
// foo/ will not match 'foo'
|
||||
? `${match}$`
|
||||
// foo matches 'foo' and 'foo/'
|
||||
: `${match}(?=$|\\/$)`
|
||||
],
|
||||
|
||||
// trailing wildcard
|
||||
[
|
||||
/(\^|\\\/)?\\\*$/,
|
||||
(_, p1) => {
|
||||
const prefix = p1
|
||||
// '\^':
|
||||
// '/*' does not match EMPTY
|
||||
// '/*' does not match everything
|
||||
|
||||
// '\\\/':
|
||||
// 'abc/*' does not match 'abc/'
|
||||
? `${p1}[^/]+`
|
||||
|
||||
// 'a*' matches 'a'
|
||||
// 'a*' matches 'aa'
|
||||
: '[^/]*'
|
||||
|
||||
return `${prefix}(?=$|\\/$)`
|
||||
}
|
||||
],
|
||||
]
|
||||
|
||||
// A simple cache, because an ignore rule only has only one certain meaning
|
||||
const regexCache = Object.create(null)
|
||||
|
||||
// @param {pattern}
|
||||
const makeRegex = (pattern, ignoreCase) => {
|
||||
let source = regexCache[pattern]
|
||||
|
||||
if (!source) {
|
||||
source = REPLACERS.reduce(
|
||||
(prev, [matcher, replacer]) =>
|
||||
prev.replace(matcher, replacer.bind(pattern)),
|
||||
pattern
|
||||
)
|
||||
regexCache[pattern] = source
|
||||
}
|
||||
|
||||
return ignoreCase
|
||||
? new RegExp(source, 'i')
|
||||
: new RegExp(source)
|
||||
}
|
||||
|
||||
const isString = subject => typeof subject === 'string'
|
||||
|
||||
// > A blank line matches no files, so it can serve as a separator for readability.
|
||||
const checkPattern = pattern => pattern
|
||||
&& isString(pattern)
|
||||
&& !REGEX_TEST_BLANK_LINE.test(pattern)
|
||||
&& !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
|
||||
|
||||
// > A line starting with # serves as a comment.
|
||||
&& pattern.indexOf('#') !== 0
|
||||
|
||||
const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF)
|
||||
|
||||
class IgnoreRule {
|
||||
constructor (
|
||||
origin,
|
||||
pattern,
|
||||
negative,
|
||||
regex
|
||||
) {
|
||||
this.origin = origin
|
||||
this.pattern = pattern
|
||||
this.negative = negative
|
||||
this.regex = regex
|
||||
}
|
||||
}
|
||||
|
||||
const createRule = (pattern, ignoreCase) => {
|
||||
const origin = pattern
|
||||
let negative = false
|
||||
|
||||
// > An optional prefix "!" which negates the pattern;
|
||||
if (pattern.indexOf('!') === 0) {
|
||||
negative = true
|
||||
pattern = pattern.substr(1)
|
||||
}
|
||||
|
||||
pattern = pattern
|
||||
// > Put a backslash ("\") in front of the first "!" for patterns that
|
||||
// > begin with a literal "!", for example, `"\!important!.txt"`.
|
||||
.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')
|
||||
// > Put a backslash ("\") in front of the first hash for patterns that
|
||||
// > begin with a hash.
|
||||
.replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#')
|
||||
|
||||
const regex = makeRegex(pattern, ignoreCase)
|
||||
|
||||
return new IgnoreRule(
|
||||
origin,
|
||||
pattern,
|
||||
negative,
|
||||
regex
|
||||
)
|
||||
}
|
||||
|
||||
const throwError = (message, Ctor) => {
|
||||
throw new Ctor(message)
|
||||
}
|
||||
|
||||
const checkPath = (path, originalPath, doThrow) => {
|
||||
if (!isString(path)) {
|
||||
return doThrow(
|
||||
`path must be a string, but got \`${originalPath}\``,
|
||||
TypeError
|
||||
)
|
||||
}
|
||||
|
||||
// We don't know if we should ignore EMPTY, so throw
|
||||
if (!path) {
|
||||
return doThrow(`path must not be empty`, TypeError)
|
||||
}
|
||||
|
||||
// Check if it is a relative path
|
||||
if (checkPath.isNotRelative(path)) {
|
||||
const r = '`path.relative()`d'
|
||||
return doThrow(
|
||||
`path should be a ${r} string, but got "${originalPath}"`,
|
||||
RangeError
|
||||
)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path)
|
||||
|
||||
checkPath.isNotRelative = isNotRelative
|
||||
checkPath.convert = p => p
|
||||
|
||||
class Ignore {
|
||||
constructor ({
|
||||
ignorecase = true,
|
||||
ignoreCase = ignorecase,
|
||||
allowRelativePaths = false
|
||||
} = {}) {
|
||||
define(this, KEY_IGNORE, true)
|
||||
|
||||
this._rules = []
|
||||
this._ignoreCase = ignoreCase
|
||||
this._allowRelativePaths = allowRelativePaths
|
||||
this._initCache()
|
||||
}
|
||||
|
||||
_initCache () {
|
||||
this._ignoreCache = Object.create(null)
|
||||
this._testCache = Object.create(null)
|
||||
}
|
||||
|
||||
_addPattern (pattern) {
|
||||
// #32
|
||||
if (pattern && pattern[KEY_IGNORE]) {
|
||||
this._rules = this._rules.concat(pattern._rules)
|
||||
this._added = true
|
||||
return
|
||||
}
|
||||
|
||||
if (checkPattern(pattern)) {
|
||||
const rule = createRule(pattern, this._ignoreCase)
|
||||
this._added = true
|
||||
this._rules.push(rule)
|
||||
}
|
||||
}
|
||||
|
||||
// @param {Array<string> | string | Ignore} pattern
|
||||
add (pattern) {
|
||||
this._added = false
|
||||
|
||||
makeArray(
|
||||
isString(pattern)
|
||||
? splitPattern(pattern)
|
||||
: pattern
|
||||
).forEach(this._addPattern, this)
|
||||
|
||||
// Some rules have just added to the ignore,
|
||||
// making the behavior changed.
|
||||
if (this._added) {
|
||||
this._initCache()
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// legacy
|
||||
addPattern (pattern) {
|
||||
return this.add(pattern)
|
||||
}
|
||||
|
||||
// | ignored : unignored
|
||||
// negative | 0:0 | 0:1 | 1:0 | 1:1
|
||||
// -------- | ------- | ------- | ------- | --------
|
||||
// 0 | TEST | TEST | SKIP | X
|
||||
// 1 | TESTIF | SKIP | TEST | X
|
||||
|
||||
// - SKIP: always skip
|
||||
// - TEST: always test
|
||||
// - TESTIF: only test if checkUnignored
|
||||
// - X: that never happen
|
||||
|
||||
// @param {boolean} whether should check if the path is unignored,
|
||||
// setting `checkUnignored` to `false` could reduce additional
|
||||
// path matching.
|
||||
|
||||
// @returns {TestResult} true if a file is ignored
|
||||
_testOne (path, checkUnignored) {
|
||||
let ignored = false
|
||||
let unignored = false
|
||||
|
||||
this._rules.forEach(rule => {
|
||||
const {negative} = rule
|
||||
if (
|
||||
unignored === negative && ignored !== unignored
|
||||
|| negative && !ignored && !unignored && !checkUnignored
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const matched = rule.regex.test(path)
|
||||
|
||||
if (matched) {
|
||||
ignored = !negative
|
||||
unignored = negative
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
ignored,
|
||||
unignored
|
||||
}
|
||||
}
|
||||
|
||||
// @returns {TestResult}
|
||||
_test (originalPath, cache, checkUnignored, slices) {
|
||||
const path = originalPath
|
||||
// Supports nullable path
|
||||
&& checkPath.convert(originalPath)
|
||||
|
||||
checkPath(
|
||||
path,
|
||||
originalPath,
|
||||
this._allowRelativePaths
|
||||
? RETURN_FALSE
|
||||
: throwError
|
||||
)
|
||||
|
||||
return this._t(path, cache, checkUnignored, slices)
|
||||
}
|
||||
|
||||
_t (path, cache, checkUnignored, slices) {
|
||||
if (path in cache) {
|
||||
return cache[path]
|
||||
}
|
||||
|
||||
if (!slices) {
|
||||
// path/to/a.js
|
||||
// ['path', 'to', 'a.js']
|
||||
slices = path.split(SLASH)
|
||||
}
|
||||
|
||||
slices.pop()
|
||||
|
||||
// If the path has no parent directory, just test it
|
||||
if (!slices.length) {
|
||||
return cache[path] = this._testOne(path, checkUnignored)
|
||||
}
|
||||
|
||||
const parent = this._t(
|
||||
slices.join(SLASH) + SLASH,
|
||||
cache,
|
||||
checkUnignored,
|
||||
slices
|
||||
)
|
||||
|
||||
// If the path contains a parent directory, check the parent first
|
||||
return cache[path] = parent.ignored
|
||||
// > It is not possible to re-include a file if a parent directory of
|
||||
// > that file is excluded.
|
||||
? parent
|
||||
: this._testOne(path, checkUnignored)
|
||||
}
|
||||
|
||||
ignores (path) {
|
||||
return this._test(path, this._ignoreCache, false).ignored
|
||||
}
|
||||
|
||||
createFilter () {
|
||||
return path => !this.ignores(path)
|
||||
}
|
||||
|
||||
filter (paths) {
|
||||
return makeArray(paths).filter(this.createFilter())
|
||||
}
|
||||
|
||||
// @returns {TestResult}
|
||||
test (path) {
|
||||
return this._test(path, this._testCache, true)
|
||||
}
|
||||
}
|
||||
|
||||
const factory = options => new Ignore(options)
|
||||
|
||||
const isPathValid = path =>
|
||||
checkPath(path && checkPath.convert(path), path, RETURN_FALSE)
|
||||
|
||||
factory.isPathValid = isPathValid
|
||||
|
||||
// Fixes typescript
|
||||
factory.default = factory
|
||||
|
||||
module.exports = factory
|
||||
|
||||
// Windows
|
||||
// --------------------------------------------------------------
|
||||
/* istanbul ignore if */
|
||||
if (
|
||||
// Detect `process` so that it can run in browsers.
|
||||
typeof process !== 'undefined'
|
||||
&& (
|
||||
process.env && process.env.IGNORE_TEST_WIN32
|
||||
|| process.platform === 'win32'
|
||||
)
|
||||
) {
|
||||
/* eslint no-control-regex: "off" */
|
||||
const makePosix = str => /^\\\\\?\\/.test(str)
|
||||
|| /["<>|\u0000-\u001F]+/u.test(str)
|
||||
? str
|
||||
: str.replace(/\\/g, '/')
|
||||
|
||||
checkPath.convert = makePosix
|
||||
|
||||
// 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/'
|
||||
// 'd:\\foo'
|
||||
const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i
|
||||
checkPath.isNotRelative = path =>
|
||||
REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path)
|
||||
|| isNotRelative(path)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_type_of.js";
|
||||
@@ -0,0 +1,3 @@
|
||||
import { type ZodErrorMap } from "../ZodError.cjs";
|
||||
declare const errorMap: ZodErrorMap;
|
||||
export = errorMap;
|
||||
@@ -0,0 +1,289 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.checkModifiers = checkModifiers;
|
||||
const ts = __importStar(require("typescript"));
|
||||
const getModifiers_1 = require("./getModifiers");
|
||||
const node_utils_1 = require("./node-utils");
|
||||
const SyntaxKind = ts.SyntaxKind;
|
||||
// `ts.nodeIsMissing`
|
||||
function nodeIsMissing(node) {
|
||||
if (node == null) {
|
||||
return true;
|
||||
}
|
||||
return (node.pos === node.end &&
|
||||
node.pos >= 0 &&
|
||||
node.kind !== SyntaxKind.EndOfFileToken);
|
||||
}
|
||||
// `ts.nodeIsPresent`
|
||||
function nodeIsPresent(node) {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
// `ts.hasAbstractModifier`
|
||||
function hasAbstractModifier(node) {
|
||||
return (0, node_utils_1.hasModifier)(SyntaxKind.AbstractKeyword, node);
|
||||
}
|
||||
// `ts.getThisParameter`
|
||||
function getThisParameter(signature) {
|
||||
if (signature.parameters.length && !ts.isJSDocSignature(signature)) {
|
||||
const thisParameter = signature.parameters[0];
|
||||
if (parameterIsThisKeyword(thisParameter)) {
|
||||
return thisParameter;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// `ts.parameterIsThisKeyword`
|
||||
function parameterIsThisKeyword(parameter) {
|
||||
return (0, node_utils_1.isThisIdentifier)(parameter.name);
|
||||
}
|
||||
// `ts.getContainingFunction`
|
||||
function getContainingFunction(node) {
|
||||
return ts.findAncestor(node.parent, ts.isFunctionLike);
|
||||
}
|
||||
// Rewrite version of `ts.nodeCanBeDecorated`
|
||||
// Returns `true` for both `useLegacyDecorators: true` and `useLegacyDecorators: false`
|
||||
function nodeCanBeDecorated(node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return true;
|
||||
case SyntaxKind.ClassExpression:
|
||||
// `ts.nodeCanBeDecorated` returns `false` if `useLegacyDecorators: true`
|
||||
return true;
|
||||
case SyntaxKind.PropertyDeclaration: {
|
||||
const { parent } = node;
|
||||
// `ts.nodeCanBeDecorated` uses this if `useLegacyDecorators: true`
|
||||
if (ts.isClassDeclaration(parent)) {
|
||||
return true;
|
||||
}
|
||||
// `ts.nodeCanBeDecorated` uses this if `useLegacyDecorators: false`
|
||||
// parent is already a ClassLike subtype; defensive check
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (ts.isClassLike(parent) && !hasAbstractModifier(node)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.MethodDeclaration: {
|
||||
const { parent } = node;
|
||||
// In `ts.nodeCanBeDecorated`
|
||||
// when `useLegacyDecorators: true` uses `ts.isClassDeclaration`
|
||||
// when `useLegacyDecorators: true` uses `ts.isClassLike`
|
||||
return (Boolean(node.body) &&
|
||||
(ts.isClassDeclaration(parent) || ts.isClassLike(parent)));
|
||||
}
|
||||
case SyntaxKind.Parameter: {
|
||||
// `ts.nodeCanBeDecorated` returns `false` if `useLegacyDecorators: false`
|
||||
const { parent } = node;
|
||||
const grandparent = parent.parent;
|
||||
return (Boolean(parent) &&
|
||||
'body' in parent &&
|
||||
Boolean(parent.body) &&
|
||||
(parent.kind === SyntaxKind.Constructor ||
|
||||
parent.kind === SyntaxKind.MethodDeclaration ||
|
||||
parent.kind === SyntaxKind.SetAccessor) &&
|
||||
getThisParameter(parent) !== node &&
|
||||
Boolean(grandparent) &&
|
||||
grandparent.kind === SyntaxKind.ClassDeclaration);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function nodeHasIllegalDecorators(node) {
|
||||
return !!('illegalDecorators' in node &&
|
||||
node.illegalDecorators?.length);
|
||||
}
|
||||
function checkModifiers(node) {
|
||||
// typescript<5.0.0
|
||||
if (nodeHasIllegalDecorators(node)) {
|
||||
throw (0, node_utils_1.createError)(node.illegalDecorators[0], 'Decorators are not valid here.');
|
||||
}
|
||||
for (const decorator of (0, getModifiers_1.getDecorators)(node,
|
||||
/* includeIllegalDecorators */ true) ?? []) {
|
||||
// `checkGrammarModifiers` function in typescript
|
||||
if (!nodeCanBeDecorated(node)) {
|
||||
if (ts.isMethodDeclaration(node) && !nodeIsPresent(node.body)) {
|
||||
throw (0, node_utils_1.createError)(decorator, 'A decorator can only decorate a method implementation, not an overload.');
|
||||
}
|
||||
else {
|
||||
throw (0, node_utils_1.createError)(decorator, 'Decorators are not valid here.');
|
||||
}
|
||||
}
|
||||
}
|
||||
const modifiers = (0, getModifiers_1.getModifiers)(node, /* includeIllegalModifiers */ true) ?? [];
|
||||
for (const modifier of modifiers) {
|
||||
if (modifier.kind !== SyntaxKind.ReadonlyKeyword) {
|
||||
if (node.kind === SyntaxKind.PropertySignature ||
|
||||
node.kind === SyntaxKind.MethodSignature) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot appear on a type member`);
|
||||
}
|
||||
if (node.kind === SyntaxKind.IndexSignature &&
|
||||
(modifier.kind !== SyntaxKind.StaticKeyword ||
|
||||
!ts.isClassLike(node.parent))) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot appear on an index signature`);
|
||||
}
|
||||
}
|
||||
if (modifier.kind !== SyntaxKind.InKeyword &&
|
||||
modifier.kind !== SyntaxKind.OutKeyword &&
|
||||
modifier.kind !== SyntaxKind.ConstKeyword &&
|
||||
node.kind === SyntaxKind.TypeParameter) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot appear on a type parameter`);
|
||||
}
|
||||
if ((modifier.kind === SyntaxKind.InKeyword ||
|
||||
modifier.kind === SyntaxKind.OutKeyword) &&
|
||||
(node.kind !== SyntaxKind.TypeParameter ||
|
||||
!(ts.isInterfaceDeclaration(node.parent) ||
|
||||
ts.isClassLike(node.parent) ||
|
||||
ts.isTypeAliasDeclaration(node.parent)))) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier can only appear on a type parameter of a class, interface or type alias`);
|
||||
}
|
||||
if (modifier.kind === SyntaxKind.ReadonlyKeyword &&
|
||||
node.kind !== SyntaxKind.PropertyDeclaration &&
|
||||
node.kind !== SyntaxKind.PropertySignature &&
|
||||
node.kind !== SyntaxKind.IndexSignature &&
|
||||
node.kind !== SyntaxKind.Parameter) {
|
||||
throw (0, node_utils_1.createError)(modifier, "'readonly' modifier can only appear on a property declaration or index signature.");
|
||||
}
|
||||
if (modifier.kind === SyntaxKind.DeclareKeyword &&
|
||||
ts.isClassLike(node.parent) &&
|
||||
!ts.isPropertyDeclaration(node)) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot appear on class elements of this kind.`);
|
||||
}
|
||||
if (modifier.kind === SyntaxKind.DeclareKeyword &&
|
||||
ts.isVariableStatement(node)) {
|
||||
const declarationKind = (0, node_utils_1.getDeclarationKind)(node.declarationList);
|
||||
if (declarationKind === 'using' || declarationKind === 'await using') {
|
||||
throw (0, node_utils_1.createError)(modifier, `'declare' modifier cannot appear on a '${declarationKind}' declaration.`);
|
||||
}
|
||||
}
|
||||
if (modifier.kind === SyntaxKind.AbstractKeyword &&
|
||||
node.kind !== SyntaxKind.ClassDeclaration &&
|
||||
node.kind !== SyntaxKind.ConstructorType &&
|
||||
node.kind !== SyntaxKind.MethodDeclaration &&
|
||||
node.kind !== SyntaxKind.PropertyDeclaration &&
|
||||
node.kind !== SyntaxKind.GetAccessor &&
|
||||
node.kind !== SyntaxKind.SetAccessor) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier can only appear on a class, method, or property declaration.`);
|
||||
}
|
||||
if ((modifier.kind === SyntaxKind.StaticKeyword ||
|
||||
modifier.kind === SyntaxKind.PublicKeyword ||
|
||||
modifier.kind === SyntaxKind.ProtectedKeyword ||
|
||||
modifier.kind === SyntaxKind.PrivateKeyword) &&
|
||||
(node.parent.kind === SyntaxKind.ModuleBlock ||
|
||||
node.parent.kind === SyntaxKind.SourceFile)) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot appear on a module or namespace element.`);
|
||||
}
|
||||
if (modifier.kind === SyntaxKind.AccessorKeyword &&
|
||||
node.kind !== SyntaxKind.PropertyDeclaration) {
|
||||
throw (0, node_utils_1.createError)(modifier, "'accessor' modifier can only appear on a property declaration.");
|
||||
}
|
||||
// `checkGrammarAsyncModifier` function in `typescript`
|
||||
if (modifier.kind === SyntaxKind.AsyncKeyword &&
|
||||
node.kind !== SyntaxKind.MethodDeclaration &&
|
||||
node.kind !== SyntaxKind.FunctionDeclaration &&
|
||||
node.kind !== SyntaxKind.FunctionExpression &&
|
||||
node.kind !== SyntaxKind.ArrowFunction) {
|
||||
throw (0, node_utils_1.createError)(modifier, "'async' modifier cannot be used here.");
|
||||
}
|
||||
// `checkGrammarModifiers` function in `typescript`
|
||||
if (node.kind === SyntaxKind.Parameter &&
|
||||
(modifier.kind === SyntaxKind.StaticKeyword ||
|
||||
modifier.kind === SyntaxKind.ExportKeyword ||
|
||||
modifier.kind === SyntaxKind.DeclareKeyword ||
|
||||
modifier.kind === SyntaxKind.AsyncKeyword)) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot appear on a parameter.`);
|
||||
}
|
||||
// `checkGrammarModifiers` function in `typescript`
|
||||
if (modifier.kind === SyntaxKind.PublicKeyword ||
|
||||
modifier.kind === SyntaxKind.ProtectedKeyword ||
|
||||
modifier.kind === SyntaxKind.PrivateKeyword) {
|
||||
for (const anotherModifier of modifiers) {
|
||||
if (anotherModifier !== modifier &&
|
||||
(anotherModifier.kind === SyntaxKind.PublicKeyword ||
|
||||
anotherModifier.kind === SyntaxKind.ProtectedKeyword ||
|
||||
anotherModifier.kind === SyntaxKind.PrivateKeyword)) {
|
||||
throw (0, node_utils_1.createError)(anotherModifier, `Accessibility modifier already seen.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// `checkParameter` function in `typescript`
|
||||
if (node.kind === SyntaxKind.Parameter &&
|
||||
// In `typescript` package, it's `ts.hasSyntacticModifier(node, ts.ModifierFlags.ParameterPropertyModifier)`
|
||||
// https://github.com/typescript-eslint/typescript-eslint/pull/6615#discussion_r1136489935
|
||||
(modifier.kind === SyntaxKind.PublicKeyword ||
|
||||
modifier.kind === SyntaxKind.PrivateKeyword ||
|
||||
modifier.kind === SyntaxKind.ProtectedKeyword ||
|
||||
modifier.kind === SyntaxKind.ReadonlyKeyword ||
|
||||
modifier.kind === SyntaxKind.OverrideKeyword)) {
|
||||
const func = getContainingFunction(node);
|
||||
if (!(func?.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
|
||||
throw (0, node_utils_1.createError)(modifier, 'A parameter property is only allowed in a constructor implementation.');
|
||||
}
|
||||
const param = node;
|
||||
if (param.dotDotDotToken) {
|
||||
throw (0, node_utils_1.createError)(modifier, 'A parameter property cannot be a rest parameter.');
|
||||
}
|
||||
if (param.name.kind === SyntaxKind.ArrayBindingPattern ||
|
||||
param.name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
throw (0, node_utils_1.createError)(modifier, 'A parameter property may not be declared using a binding pattern.');
|
||||
}
|
||||
}
|
||||
checkObjectPropertyModifier(node, modifier);
|
||||
}
|
||||
// `ts.getModifiers()` can't access invalid modifiers on object properties
|
||||
// Eg: `({declare a: 1})`
|
||||
// See https://github.com/typescript-eslint/typescript-eslint/pull/11931#discussion_r2678961730
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- incorrect type
|
||||
if (node.parent?.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
// @ts-expect-error intentional to access deprecated `node.modifiers`
|
||||
for (const modifier of node.modifiers ??
|
||||
[]) {
|
||||
if (ts.isDecorator(modifier) || modifiers.includes(modifier)) {
|
||||
continue;
|
||||
}
|
||||
checkObjectPropertyModifier(node, modifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
function checkObjectPropertyModifier(node, modifier) {
|
||||
// From `checkGrammarObjectLiteralExpression` function in `typescript`
|
||||
if ((modifier.kind !== SyntaxKind.AsyncKeyword ||
|
||||
node.kind !== SyntaxKind.MethodDeclaration) &&
|
||||
node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
throw (0, node_utils_1.createError)(modifier, `'${ts.tokenToString(modifier.kind)}' modifier cannot be used here.`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
# once
|
||||
|
||||
Only call a function once.
|
||||
|
||||
## usage
|
||||
|
||||
```javascript
|
||||
var once = require('once')
|
||||
|
||||
function load (file, cb) {
|
||||
cb = once(cb)
|
||||
loader.load('file')
|
||||
loader.once('load', cb)
|
||||
loader.once('error', cb)
|
||||
}
|
||||
```
|
||||
|
||||
Or add to the Function.prototype in a responsible way:
|
||||
|
||||
```javascript
|
||||
// only has to be done once
|
||||
require('once').proto()
|
||||
|
||||
function load (file, cb) {
|
||||
cb = cb.once()
|
||||
loader.load('file')
|
||||
loader.once('load', cb)
|
||||
loader.once('error', cb)
|
||||
}
|
||||
```
|
||||
|
||||
Ironically, the prototype feature makes this module twice as
|
||||
complicated as necessary.
|
||||
|
||||
To check whether you function has been called, use `fn.called`. Once the
|
||||
function is called for the first time the return value of the original
|
||||
function is saved in `fn.value` and subsequent calls will continue to
|
||||
return this value.
|
||||
|
||||
```javascript
|
||||
var once = require('once')
|
||||
|
||||
function load (cb) {
|
||||
cb = once(cb)
|
||||
var stream = createStream()
|
||||
stream.once('data', cb)
|
||||
stream.once('end', function () {
|
||||
if (!cb.called) cb(new Error('not found'))
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## `once.strict(func)`
|
||||
|
||||
Throw an error if the function is called twice.
|
||||
|
||||
Some functions are expected to be called only once. Using `once` for them would
|
||||
potentially hide logical errors.
|
||||
|
||||
In the example below, the `greet` function has to call the callback only once:
|
||||
|
||||
```javascript
|
||||
function greet (name, cb) {
|
||||
// return is missing from the if statement
|
||||
// when no name is passed, the callback is called twice
|
||||
if (!name) cb('Hello anonymous')
|
||||
cb('Hello ' + name)
|
||||
}
|
||||
|
||||
function log (msg) {
|
||||
console.log(msg)
|
||||
}
|
||||
|
||||
// this will print 'Hello anonymous' but the logical error will be missed
|
||||
greet(null, once(msg))
|
||||
|
||||
// once.strict will print 'Hello anonymous' and throw an error when the callback will be called the second time
|
||||
greet(null, once.strict(msg))
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
// This file is autogenerated by build-prefixes.js. DO NOT EDIT!
|
||||
|
||||
exports.Features = {
|
||||
Nesting: 1,
|
||||
NotSelectorList: 2,
|
||||
DirSelector: 4,
|
||||
LangSelectorList: 8,
|
||||
IsSelector: 16,
|
||||
TextDecorationThicknessPercent: 32,
|
||||
MediaIntervalSyntax: 64,
|
||||
MediaRangeSyntax: 128,
|
||||
CustomMediaQueries: 256,
|
||||
ClampFunction: 512,
|
||||
ColorFunction: 1024,
|
||||
OklabColors: 2048,
|
||||
LabColors: 4096,
|
||||
P3Colors: 8192,
|
||||
HexAlphaColors: 16384,
|
||||
SpaceSeparatedColorNotation: 32768,
|
||||
FontFamilySystemUi: 65536,
|
||||
DoublePositionGradients: 131072,
|
||||
VendorPrefixes: 262144,
|
||||
LogicalProperties: 524288,
|
||||
LightDark: 1048576,
|
||||
Selectors: 31,
|
||||
MediaQueries: 448,
|
||||
Colors: 1113088,
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
|
||||
var _inherits = require("./_inherits.cjs");
|
||||
var _set_prototype_of = require("./_set_prototype_of.cjs");
|
||||
|
||||
function _wrap_reg_exp(re, groups, source) {
|
||||
exports._ = _wrap_reg_exp = function(re, groups, source) {
|
||||
return new WrappedRegExp(re, undefined, groups, source);
|
||||
};
|
||||
var _super = RegExp.prototype;
|
||||
var _groups = new WeakMap();
|
||||
var _sources = new WeakMap();
|
||||
var _native_source = Object.getOwnPropertyDescriptor(_super, "source").get;
|
||||
function WrappedRegExp(re, flags, groups, source) {
|
||||
var _re = new RegExp(re, flags);
|
||||
_groups.set(_re, groups || _groups.get(re));
|
||||
_sources.set(_re, source !== undefined ? source : _sources.get(re));
|
||||
return _set_prototype_of._(_re, WrappedRegExp.prototype);
|
||||
}
|
||||
_inherits._(WrappedRegExp, RegExp);
|
||||
Object.defineProperty(WrappedRegExp.prototype, "source", {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
var source = _sources.get(this);
|
||||
if (source !== undefined) {
|
||||
try {
|
||||
new RegExp(source, this.flags);
|
||||
return source;
|
||||
} catch (_) {}
|
||||
}
|
||||
return _native_source.call(this);
|
||||
}
|
||||
});
|
||||
WrappedRegExp.prototype.exec = function(str) {
|
||||
var result = _super.exec.call(this, str);
|
||||
if (result) {
|
||||
result.groups = buildGroups(result, this);
|
||||
var indices = result.indices;
|
||||
if (indices) indices.groups = buildGroups(indices, this);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
WrappedRegExp.prototype[Symbol.replace] = function(str, substitution) {
|
||||
if (typeof substitution === "string") {
|
||||
var groups = _groups.get(this);
|
||||
return _super[Symbol.replace].call(
|
||||
this,
|
||||
str,
|
||||
substitution.replace(/\$<([^>]+)>/g, function(_, name) {
|
||||
var group = groups ? groups[name] : undefined;
|
||||
if (group === undefined) return "";
|
||||
return "$" + (Array.isArray(group) ? group.join("$") : group);
|
||||
})
|
||||
);
|
||||
}
|
||||
if (typeof substitution === "function") {
|
||||
var _this = this;
|
||||
return _super[Symbol.replace].call(this, str, function() {
|
||||
var args = arguments;
|
||||
if (typeof args[args.length - 1] !== "object") {
|
||||
args = [].slice.call(args);
|
||||
args.push(buildGroups(args, _this));
|
||||
}
|
||||
return substitution.apply(this, args);
|
||||
});
|
||||
}
|
||||
return _super[Symbol.replace].call(this, str, substitution);
|
||||
};
|
||||
function buildGroups(result, re) {
|
||||
var g = _groups.get(re);
|
||||
return Object.keys(g).reduce(function(groups, name) {
|
||||
var i = g[name];
|
||||
if (typeof i === "number") groups[name] = result[i];
|
||||
else {
|
||||
var k = 0;
|
||||
while (result[i[k]] === undefined && k + 1 < i.length) k++;
|
||||
groups[name] = result[i[k]];
|
||||
}
|
||||
return groups;
|
||||
}, Object.create(null));
|
||||
}
|
||||
return _wrap_reg_exp.apply(this, arguments);
|
||||
}
|
||||
exports._ = _wrap_reg_exp;
|
||||
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const util_1 = require("../util");
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'no-duplicate-enum-values',
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Disallow duplicate enum member values',
|
||||
recommended: 'recommended',
|
||||
},
|
||||
hasSuggestions: false,
|
||||
messages: {
|
||||
duplicateValue: 'Duplicate enum member value {{value}}.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
function isStringLiteral(node) {
|
||||
return (node.type === utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'string');
|
||||
}
|
||||
function isNumberLiteral(node) {
|
||||
return (node.type === utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'number');
|
||||
}
|
||||
function isSupportedUnary(node) {
|
||||
return (node.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
||||
['-', '+'].includes(node.operator));
|
||||
}
|
||||
function isStaticTemplateLiteral(node) {
|
||||
return (node.type === utils_1.AST_NODE_TYPES.TemplateLiteral &&
|
||||
node.expressions.length === 0 &&
|
||||
node.quasis.length === 1);
|
||||
}
|
||||
function getMemberValue(initializer) {
|
||||
switch (true) {
|
||||
case isStringLiteral(initializer):
|
||||
case isNumberLiteral(initializer):
|
||||
return initializer.value;
|
||||
case isSupportedUnary(initializer): {
|
||||
const inner = Number(getMemberValue(initializer.argument));
|
||||
if (Number.isNaN(inner)) {
|
||||
return undefined;
|
||||
}
|
||||
return initializer.operator === '-' ? -inner : inner;
|
||||
}
|
||||
case isStaticTemplateLiteral(initializer):
|
||||
return initializer.quasis[0].value.cooked ?? undefined;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
return {
|
||||
TSEnumDeclaration(node) {
|
||||
const enumMembers = node.body.members;
|
||||
const seenValues = [];
|
||||
enumMembers.forEach(member => {
|
||||
if (member.initializer == null) {
|
||||
return;
|
||||
}
|
||||
const value = getMemberValue(member.initializer);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
const isAlreadyPresent = seenValues.some(seenValue => Object.is(seenValue, value));
|
||||
if (isAlreadyPresent) {
|
||||
context.report({
|
||||
node: member,
|
||||
messageId: 'duplicateValue',
|
||||
data: {
|
||||
value,
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
seenValues.push(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user