WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createIdGenerator = createIdGenerator;
|
||||
exports.resetIds = resetIds;
|
||||
const ID_CACHE = new Map();
|
||||
let NEXT_KEY = 0;
|
||||
function createIdGenerator() {
|
||||
const key = (NEXT_KEY += 1);
|
||||
ID_CACHE.set(key, 0);
|
||||
return () => {
|
||||
const current = ID_CACHE.get(key) ?? 0;
|
||||
const next = current + 1;
|
||||
ID_CACHE.set(key, next);
|
||||
return next;
|
||||
};
|
||||
}
|
||||
function resetIds() {
|
||||
ID_CACHE.clear();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const util_1 = require("../util");
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'no-non-null-asserted-optional-chain',
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Disallow non-null assertions after an optional chain expression',
|
||||
recommended: 'recommended',
|
||||
},
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
noNonNullOptionalChain: 'Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong.',
|
||||
suggestRemovingNonNull: 'You should remove the non-null assertion.',
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
defaultOptions: [],
|
||||
create(context) {
|
||||
return {
|
||||
// non-nulling a wrapped chain will scrub all nulls introduced by the chain
|
||||
// (x?.y)!
|
||||
// (x?.())!
|
||||
'TSNonNullExpression > ChainExpression'(node) {
|
||||
// selector guarantees this assertion
|
||||
const parent = node.parent;
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noNonNullOptionalChain',
|
||||
// use a suggestion instead of a fixer, because this can obviously break type checks
|
||||
suggest: [
|
||||
{
|
||||
messageId: 'suggestRemovingNonNull',
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([
|
||||
parent.range[1] - 1,
|
||||
parent.range[1],
|
||||
]);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
// non-nulling at the end of a chain will scrub all nulls introduced by the chain
|
||||
// x?.y!
|
||||
// x?.()!
|
||||
'ChainExpression > TSNonNullExpression'(node) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noNonNullOptionalChain',
|
||||
// use a suggestion instead of a fixer, because this can obviously break type checks
|
||||
suggest: [
|
||||
{
|
||||
messageId: 'suggestRemovingNonNull',
|
||||
fix(fixer) {
|
||||
return fixer.removeRange([node.range[1] - 1, node.range[1]]);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
export * from './address-lookup-table';
|
||||
export * from './compute-budget';
|
||||
export * from './ed25519';
|
||||
export * from './secp256k1';
|
||||
export * from './stake';
|
||||
export * from './system';
|
||||
export * from './vote';
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const promisify = require('es6-promisify');
|
||||
const jayson = require('../../../');
|
||||
const promiseUtils = require('../utils');
|
||||
|
||||
/**
|
||||
* Constructor for a Jayson Promise Client Http
|
||||
* @see Client
|
||||
* @class PromiseClientHttps
|
||||
* @extends ClientHttps
|
||||
* @return {PromiseClientHttps}
|
||||
*/
|
||||
const PromiseClientHttps = function(options) {
|
||||
if(!(this instanceof PromiseClientHttps)) {
|
||||
return new PromiseClientHttps(options);
|
||||
}
|
||||
jayson.Client.https.apply(this, arguments);
|
||||
this.request = promiseUtils.wrapClientRequestMethod(this.request.bind(this));
|
||||
};
|
||||
require('util').inherits(PromiseClientHttps, jayson.Client.https);
|
||||
|
||||
module.exports = PromiseClientHttps;
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"name": "@typescript-eslint/eslint-plugin",
|
||||
"version": "8.67.0",
|
||||
"description": "TypeScript plugin for ESLint",
|
||||
"files": [
|
||||
"dist",
|
||||
"!**/*.tsbuildinfo",
|
||||
"index.d.ts",
|
||||
"raw-plugin.d.ts",
|
||||
"rules.d.ts"
|
||||
],
|
||||
"type": "commonjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./package.json": "./package.json",
|
||||
"./use-at-your-own-risk/rules": {
|
||||
"types": "./rules.d.ts",
|
||||
"default": "./dist/rules/index.js"
|
||||
},
|
||||
"./use-at-your-own-risk/raw-plugin": {
|
||||
"types": "./raw-plugin.d.ts",
|
||||
"default": "./dist/raw-plugin.js"
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/typescript-eslint/typescript-eslint.git",
|
||||
"directory": "packages/eslint-plugin"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/typescript-eslint/typescript-eslint/issues"
|
||||
},
|
||||
"homepage": "https://typescript-eslint.io/packages/eslint-plugin",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"eslint",
|
||||
"eslintplugin",
|
||||
"eslint-plugin",
|
||||
"typescript"
|
||||
],
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.12.2",
|
||||
"ignore": "^7.0.5",
|
||||
"natural-compare": "^1.4.0",
|
||||
"ts-api-utils": "^2.5.0",
|
||||
"@typescript-eslint/scope-manager": "8.67.0",
|
||||
"@typescript-eslint/type-utils": "8.67.0",
|
||||
"@typescript-eslint/visitor-keys": "8.67.0",
|
||||
"@typescript-eslint/utils": "8.67.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/natural-compare": "^1.4.3",
|
||||
"@types/react": "^18.3.21",
|
||||
"@typescript/native": "npm:typescript@^7.0.2",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"ajv": "^6.12.6",
|
||||
"eslint": "^10.0.0",
|
||||
"json-schema": "^0.4.0",
|
||||
"markdown-table": "^3.0.4",
|
||||
"marked": "^15.0.12",
|
||||
"mdast-util-from-markdown": "^2.0.2",
|
||||
"mdast-util-mdx": "^3.0.0",
|
||||
"micromark-extension-mdxjs": "^3.0.0",
|
||||
"prettier": "3.9.5",
|
||||
"rimraf": "^5.0.10",
|
||||
"title-case": "^4.3.2",
|
||||
"tsx": "^4.7.2",
|
||||
"typescript": ">=4.8.4 <6.1.0",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vitest": "^4.0.18",
|
||||
"@typescript-eslint/rule-schema-to-typescript-types": "8.67.0",
|
||||
"@typescript-eslint/rule-tester": "8.67.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
||||
"typescript": ">=4.8.4 <6.1.0",
|
||||
"@typescript-eslint/parser": "^8.67.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"nx": {
|
||||
"name": "eslint-plugin",
|
||||
"includedScripts": [
|
||||
"clean"
|
||||
],
|
||||
"targets": {
|
||||
"generate-breaking-changes": {
|
||||
"command": "tsx tools/generate-breaking-changes.mts",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}"
|
||||
},
|
||||
"dependsOn": [
|
||||
"type-utils:build"
|
||||
]
|
||||
},
|
||||
"lint": {
|
||||
"command": "eslint"
|
||||
},
|
||||
"typecheck:tsgo": {},
|
||||
"attw-check": {
|
||||
"cache": false,
|
||||
"dependsOn": [
|
||||
"build"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "{projectRoot}"
|
||||
},
|
||||
"command": "pnpm pack --out attw-check.tgz && attw attw-check.tgz --profile node16 --exclude-entrypoints use-at-your-own-risk/raw-plugin --exclude-entrypoints use-at-your-own-risk/rules --ignore-rules named-exports"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm -w exec nx build",
|
||||
"clean": "rimraf dist/ coverage/",
|
||||
"format": "pnpm -w run format",
|
||||
"generate-breaking-changes": "tsx tools/generate-breaking-changes.mts",
|
||||
"generate-configs": "pnpm -w run generate-configs",
|
||||
"lint": "pnpm -w exec nx lint",
|
||||
"test": "pnpm -w exec nx test",
|
||||
"typecheck": "pnpm -w exec nx typecheck",
|
||||
"typecheck:tsgo": "pnpm -w exec nx typecheck:tsgo",
|
||||
"attw-check": "pnpm -w exec nx attw-check"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
function _initializerWarningHelper(r, e) {
|
||||
throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform.");
|
||||
}
|
||||
export { _initializerWarningHelper as default };
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Socket } from 'node:net'
|
||||
import { URL } from 'node:url'
|
||||
import buildConnector from './connector'
|
||||
import Dispatcher from './dispatcher'
|
||||
|
||||
declare namespace DiagnosticsChannel {
|
||||
interface Request {
|
||||
origin?: string | URL;
|
||||
completed: boolean;
|
||||
method?: Dispatcher.HttpMethod;
|
||||
path: string;
|
||||
headers: any;
|
||||
}
|
||||
interface Response {
|
||||
statusCode: number;
|
||||
statusText: string;
|
||||
headers: Array<Buffer>;
|
||||
}
|
||||
interface ConnectParams {
|
||||
host: URL['host'];
|
||||
hostname: URL['hostname'];
|
||||
protocol: URL['protocol'];
|
||||
port: URL['port'];
|
||||
servername: string | null;
|
||||
}
|
||||
type Connector = buildConnector.connector
|
||||
export interface RequestCreateMessage {
|
||||
request: Request;
|
||||
}
|
||||
export interface RequestBodySentMessage {
|
||||
request: Request;
|
||||
}
|
||||
|
||||
export interface RequestBodyChunkSentMessage {
|
||||
request: Request;
|
||||
chunk: Uint8Array | string;
|
||||
}
|
||||
export interface RequestBodyChunkReceivedMessage {
|
||||
request: Request;
|
||||
chunk: Buffer;
|
||||
}
|
||||
export interface RequestHeadersMessage {
|
||||
request: Request;
|
||||
response: Response;
|
||||
}
|
||||
export interface RequestTrailersMessage {
|
||||
request: Request;
|
||||
trailers: Array<Buffer>;
|
||||
}
|
||||
export interface RequestErrorMessage {
|
||||
request: Request;
|
||||
error: Error;
|
||||
}
|
||||
export interface ClientSendHeadersMessage {
|
||||
request: Request;
|
||||
headers: string;
|
||||
socket: Socket;
|
||||
}
|
||||
export interface ClientBeforeConnectMessage {
|
||||
connectParams: ConnectParams;
|
||||
connector: Connector;
|
||||
}
|
||||
export interface ClientConnectedMessage {
|
||||
socket: Socket;
|
||||
connectParams: ConnectParams;
|
||||
connector: Connector;
|
||||
}
|
||||
export interface ClientConnectErrorMessage {
|
||||
error: Error;
|
||||
socket: Socket;
|
||||
connectParams: ConnectParams;
|
||||
connector: Connector;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { TypeOrValueSpecifier } from '../util';
|
||||
export type MessageIds = 'rejectAnError';
|
||||
export type Options = [
|
||||
{
|
||||
allow?: TypeOrValueSpecifier[];
|
||||
allowEmptyReject?: boolean;
|
||||
allowThrowingAny?: boolean;
|
||||
allowThrowingUnknown?: boolean;
|
||||
}
|
||||
];
|
||||
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"rejectAnError", Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,2 @@
|
||||
import type { LibDefinition } from '../variable';
|
||||
export declare const lib: ReadonlyMap<string, LibDefinition>;
|
||||
@@ -0,0 +1,601 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.collectVariables = collectVariables;
|
||||
const scope_manager_1 = require("@typescript-eslint/scope-manager");
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const isTypeImport_1 = require("./isTypeImport");
|
||||
const referenceContainsTypePredicate_1 = require("./referenceContainsTypePredicate");
|
||||
const referenceContainsTypeQuery_1 = require("./referenceContainsTypeQuery");
|
||||
/**
|
||||
* This class leverages an AST visitor to mark variables as used via the
|
||||
* `eslintUsed` property.
|
||||
*/
|
||||
class UnusedVarsVisitor extends scope_manager_1.Visitor {
|
||||
/**
|
||||
* We keep a weak cache so that multiple rules can share the calculation
|
||||
*/
|
||||
static RESULTS_CACHE = new WeakMap();
|
||||
ClassDeclaration = this.visitClass;
|
||||
ClassExpression = this.visitClass;
|
||||
ForInStatement = this.visitForInForOf;
|
||||
ForOfStatement = this.visitForInForOf;
|
||||
//#region HELPERS
|
||||
FunctionDeclaration = this.visitFunction;
|
||||
FunctionExpression = this.visitFunction;
|
||||
MethodDefinition = this.visitSetter;
|
||||
Property = this.visitSetter;
|
||||
TSCallSignatureDeclaration = this.visitFunctionTypeSignature;
|
||||
TSConstructorType = this.visitFunctionTypeSignature;
|
||||
TSConstructSignatureDeclaration = this.visitFunctionTypeSignature;
|
||||
TSDeclareFunction = this.visitFunctionTypeSignature;
|
||||
TSEmptyBodyFunctionExpression = this.visitFunctionTypeSignature;
|
||||
//#endregion HELPERS
|
||||
//#region VISITORS
|
||||
// NOTE - This is a simple visitor - meaning it does not support selectors
|
||||
TSFunctionType = this.visitFunctionTypeSignature;
|
||||
TSMethodSignature = this.visitFunctionTypeSignature;
|
||||
#scopeManager;
|
||||
constructor(scopeManager) {
|
||||
super({
|
||||
visitChildrenEvenIfSelectorExists: true,
|
||||
});
|
||||
this.#scopeManager = scopeManager;
|
||||
}
|
||||
static collectUnusedVariables(program, scopeManager) {
|
||||
const cached = this.RESULTS_CACHE.get(program);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const visitor = new this(scopeManager);
|
||||
visitor.visit(program);
|
||||
const unusedVars = visitor.collectUnusedVariables(visitor.getScope(program));
|
||||
this.RESULTS_CACHE.set(program, unusedVars);
|
||||
return unusedVars;
|
||||
}
|
||||
Identifier(node) {
|
||||
const scope = this.getScope(node);
|
||||
if (scope.type === utils_1.TSESLint.Scope.ScopeType.function &&
|
||||
node.name === 'this' &&
|
||||
// this parameters should always be considered used as they're pseudo-parameters
|
||||
'params' in scope.block &&
|
||||
scope.block.params.includes(node)) {
|
||||
this.markVariableAsUsed(node);
|
||||
}
|
||||
}
|
||||
TSEnumDeclaration(node) {
|
||||
// enum members create variables because they can be referenced within the enum,
|
||||
// but they obviously aren't unused variables for the purposes of this rule.
|
||||
const scope = this.getScope(node);
|
||||
for (const variable of scope.variables) {
|
||||
this.markVariableAsUsed(variable);
|
||||
}
|
||||
}
|
||||
TSMappedType(node) {
|
||||
// mapped types create a variable for their type name, but it's not necessary to reference it,
|
||||
// so we shouldn't consider it as unused for the purpose of this rule.
|
||||
this.markVariableAsUsed(node.key);
|
||||
}
|
||||
TSModuleDeclaration(node) {
|
||||
// -- global augmentation can be in any file, and they do not need exports
|
||||
if (node.kind === 'global') {
|
||||
this.markVariableAsUsed('global', node.parent);
|
||||
}
|
||||
}
|
||||
TSParameterProperty(node) {
|
||||
let identifier;
|
||||
switch (node.parameter.type) {
|
||||
case utils_1.AST_NODE_TYPES.AssignmentPattern:
|
||||
identifier = node.parameter.left;
|
||||
break;
|
||||
case utils_1.AST_NODE_TYPES.Identifier:
|
||||
identifier = node.parameter;
|
||||
break;
|
||||
}
|
||||
this.markVariableAsUsed(identifier);
|
||||
}
|
||||
collectUnusedVariables(scope, variables = {
|
||||
unusedVariables: new Set(),
|
||||
usedVariables: new Set(),
|
||||
}) {
|
||||
if (
|
||||
// skip function expression names
|
||||
// this scope is created just to house the variable that allows a function
|
||||
// expression to self-reference if it has a name defined
|
||||
!scope.functionExpressionScope) {
|
||||
for (const variable of scope.variables) {
|
||||
// cases that we don't want to treat as used or unused
|
||||
if (
|
||||
// implicit lib variables (from @typescript-eslint/scope-manager)
|
||||
// these aren't variables that should be checked ever
|
||||
variable instanceof scope_manager_1.ImplicitLibVariable) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
// variables marked with markVariableAsUsed()
|
||||
variable.eslintUsed ||
|
||||
// basic exported variables
|
||||
isExported(variable) ||
|
||||
// variables implicitly exported via a merged declaration
|
||||
isMergeableExported(variable) ||
|
||||
// used variables
|
||||
isUsedVariable(variable)) {
|
||||
variables.usedVariables.add(variable);
|
||||
}
|
||||
else {
|
||||
variables.unusedVariables.add(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const childScope of scope.childScopes) {
|
||||
this.collectUnusedVariables(childScope, variables);
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
getScope(currentNode) {
|
||||
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
|
||||
const inner = currentNode.type !== utils_1.AST_NODE_TYPES.Program;
|
||||
let node = currentNode;
|
||||
while (node) {
|
||||
const scope = this.#scopeManager.acquire(node, inner);
|
||||
if (scope) {
|
||||
if (scope.type === scope_manager_1.ScopeType.functionExpressionName) {
|
||||
return scope.childScopes[0];
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return this.#scopeManager.scopes[0];
|
||||
}
|
||||
markVariableAsUsed(variableOrIdentifierOrName, parent) {
|
||||
if (typeof variableOrIdentifierOrName !== 'string' &&
|
||||
!('type' in variableOrIdentifierOrName)) {
|
||||
variableOrIdentifierOrName.eslintUsed = true;
|
||||
return;
|
||||
}
|
||||
let name;
|
||||
let node;
|
||||
if (typeof variableOrIdentifierOrName === 'string') {
|
||||
name = variableOrIdentifierOrName;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
node = parent;
|
||||
}
|
||||
else {
|
||||
name = variableOrIdentifierOrName.name;
|
||||
node = variableOrIdentifierOrName;
|
||||
}
|
||||
let currentScope = this.getScope(node);
|
||||
while (currentScope) {
|
||||
const variable = currentScope.variables.find(scopeVar => scopeVar.name === name);
|
||||
if (variable) {
|
||||
variable.eslintUsed = true;
|
||||
return;
|
||||
}
|
||||
currentScope = currentScope.upper;
|
||||
}
|
||||
}
|
||||
visitClass(node) {
|
||||
// skip a variable of class itself name in the class scope
|
||||
const scope = this.getScope(node);
|
||||
for (const variable of scope.variables) {
|
||||
if (variable.identifiers[0] === scope.block.id) {
|
||||
this.markVariableAsUsed(variable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
visitForInForOf(node) {
|
||||
/**
|
||||
* (Brad Zacher): I hate that this has to exist.
|
||||
* But it is required for compat with the base ESLint rule.
|
||||
*
|
||||
* In 2015, ESLint decided to add an exception for these two specific cases
|
||||
* ```
|
||||
* for (var key in object) return;
|
||||
*
|
||||
* var key;
|
||||
* for (key in object) return;
|
||||
* ```
|
||||
*
|
||||
* I disagree with it, but what are you going to do...
|
||||
*
|
||||
* https://github.com/eslint/eslint/issues/2342
|
||||
*/
|
||||
let idOrVariable;
|
||||
if (node.left.type === utils_1.AST_NODE_TYPES.VariableDeclaration) {
|
||||
const variable = this.#scopeManager.getDeclaredVariables(node.left).at(0);
|
||||
if (!variable) {
|
||||
return;
|
||||
}
|
||||
idOrVariable = variable;
|
||||
}
|
||||
if (node.left.type === utils_1.AST_NODE_TYPES.Identifier) {
|
||||
idOrVariable = node.left;
|
||||
}
|
||||
if (idOrVariable == null) {
|
||||
return;
|
||||
}
|
||||
let body = node.body;
|
||||
if (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
||||
if (node.body.body.length !== 1) {
|
||||
return;
|
||||
}
|
||||
body = node.body.body[0];
|
||||
}
|
||||
if (body.type !== utils_1.AST_NODE_TYPES.ReturnStatement) {
|
||||
return;
|
||||
}
|
||||
this.markVariableAsUsed(idOrVariable);
|
||||
}
|
||||
visitFunction(node) {
|
||||
const scope = this.getScope(node);
|
||||
// skip implicit "arguments" variable
|
||||
const variable = scope.set.get('arguments');
|
||||
if (variable?.defs.length === 0) {
|
||||
this.markVariableAsUsed(variable);
|
||||
}
|
||||
}
|
||||
visitFunctionTypeSignature(node) {
|
||||
// function type signature params create variables because they can be referenced within the signature,
|
||||
// but they obviously aren't unused variables for the purposes of this rule.
|
||||
for (const param of node.params) {
|
||||
this.visitPattern(param, name => {
|
||||
this.markVariableAsUsed(name);
|
||||
});
|
||||
}
|
||||
}
|
||||
visitSetter(node) {
|
||||
if (node.kind === 'set') {
|
||||
// ignore setter parameters because they're syntactically required to exist
|
||||
for (const param of node.value.params) {
|
||||
this.visitPattern(param, id => {
|
||||
this.markVariableAsUsed(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//#region private helpers
|
||||
/**
|
||||
* Checks the position of given nodes.
|
||||
* @param inner A node which is expected as inside.
|
||||
* @param outer A node which is expected as outside.
|
||||
* @returns `true` if the `inner` node exists in the `outer` node.
|
||||
*/
|
||||
function isInside(inner, outer) {
|
||||
return inner.range[0] >= outer.range[0] && inner.range[1] <= outer.range[1];
|
||||
}
|
||||
/**
|
||||
* Determine if an identifier is referencing an enclosing name.
|
||||
* This only applies to declarations that create their own scope (modules, functions, classes)
|
||||
* @param ref The reference to check.
|
||||
* @param nodes The candidate function nodes.
|
||||
* @returns True if it's a self-reference, false if not.
|
||||
*/
|
||||
function isSelfReference(ref, nodes) {
|
||||
let scope = ref.from;
|
||||
while (scope) {
|
||||
if (nodes.has(scope.block)) {
|
||||
return true;
|
||||
}
|
||||
scope = scope.upper;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const MERGEABLE_TYPES = new Set([
|
||||
utils_1.AST_NODE_TYPES.ClassDeclaration,
|
||||
utils_1.AST_NODE_TYPES.FunctionDeclaration,
|
||||
utils_1.AST_NODE_TYPES.TSInterfaceDeclaration,
|
||||
utils_1.AST_NODE_TYPES.TSModuleDeclaration,
|
||||
utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration,
|
||||
]);
|
||||
/**
|
||||
* Determine if the variable is directly exported
|
||||
* @param variable the variable to check
|
||||
*/
|
||||
function isMergeableExported(variable) {
|
||||
// If all of the merged things are of the same type, TS will error if not all of them are exported - so we only need to find one
|
||||
for (const def of variable.defs) {
|
||||
// parameters can never be exported.
|
||||
// their `node` prop points to the function decl, which can be exported
|
||||
// so we need to special case them
|
||||
if (def.type === utils_1.TSESLint.Scope.DefinitionType.Parameter) {
|
||||
continue;
|
||||
}
|
||||
if ((MERGEABLE_TYPES.has(def.node.type) &&
|
||||
def.node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration) ||
|
||||
def.node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Determines if a given variable is being exported from a module.
|
||||
* @param variable eslint-scope variable object.
|
||||
* @returns True if the variable is exported, false if not.
|
||||
*/
|
||||
function isExported(variable) {
|
||||
return variable.defs.some(definition => {
|
||||
let node = definition.node;
|
||||
if (node.type === utils_1.AST_NODE_TYPES.VariableDeclarator) {
|
||||
node = node.parent;
|
||||
}
|
||||
else if (definition.type === utils_1.TSESLint.Scope.DefinitionType.Parameter) {
|
||||
return false;
|
||||
}
|
||||
return node.parent.type.startsWith('Export');
|
||||
});
|
||||
}
|
||||
const LOGICAL_ASSIGNMENT_OPERATORS = new Set(['??=', '&&=', '||=']);
|
||||
/**
|
||||
* Determines if the variable is used.
|
||||
* @param variable The variable to check.
|
||||
* @returns True if the variable is used
|
||||
*/
|
||||
function isUsedVariable(variable) {
|
||||
/**
|
||||
* Gets a list of function definitions for a specified variable.
|
||||
* @param variable eslint-scope variable object.
|
||||
* @returns Function nodes.
|
||||
*/
|
||||
function getFunctionDefinitions(variable) {
|
||||
const functionDefinitions = new Set();
|
||||
variable.defs.forEach(def => {
|
||||
// FunctionDeclarations
|
||||
if (def.type === utils_1.TSESLint.Scope.DefinitionType.FunctionName) {
|
||||
functionDefinitions.add(def.node);
|
||||
}
|
||||
// FunctionExpressions
|
||||
if (def.type === utils_1.TSESLint.Scope.DefinitionType.Variable &&
|
||||
(def.node.init?.type === utils_1.AST_NODE_TYPES.FunctionExpression ||
|
||||
def.node.init?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression)) {
|
||||
functionDefinitions.add(def.node.init);
|
||||
}
|
||||
});
|
||||
return functionDefinitions;
|
||||
}
|
||||
function getTypeDeclarations(variable) {
|
||||
const nodes = new Set();
|
||||
variable.defs.forEach(def => {
|
||||
if (def.node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration ||
|
||||
def.node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
||||
nodes.add(def.node);
|
||||
}
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
function getModuleDeclarations(variable) {
|
||||
const nodes = new Set();
|
||||
variable.defs.forEach(def => {
|
||||
if (def.node.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration) {
|
||||
nodes.add(def.node);
|
||||
}
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
function getEnumDeclarations(variable) {
|
||||
const nodes = new Set();
|
||||
variable.defs.forEach(def => {
|
||||
if (def.node.type === utils_1.AST_NODE_TYPES.TSEnumDeclaration) {
|
||||
nodes.add(def.node);
|
||||
}
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
/**
|
||||
* Checks if the ref is contained within one of the given nodes
|
||||
*/
|
||||
function isInsideOneOf(ref, nodes) {
|
||||
for (const node of nodes) {
|
||||
if (isInside(ref.identifier, node)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Checks whether a given node is unused expression or not.
|
||||
* @param node The node itself
|
||||
* @returns The node is an unused expression.
|
||||
*/
|
||||
function isUnusedExpression(node) {
|
||||
const parent = node.parent;
|
||||
if (parent.type === utils_1.AST_NODE_TYPES.ExpressionStatement) {
|
||||
return true;
|
||||
}
|
||||
if (parent.type === utils_1.AST_NODE_TYPES.SequenceExpression) {
|
||||
const isLastExpression = parent.expressions[parent.expressions.length - 1] === node;
|
||||
if (!isLastExpression) {
|
||||
return true;
|
||||
}
|
||||
return isUnusedExpression(parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* If a given reference is left-hand side of an assignment, this gets
|
||||
* the right-hand side node of the assignment.
|
||||
*
|
||||
* In the following cases, this returns null.
|
||||
*
|
||||
* - The reference is not the LHS of an assignment expression.
|
||||
* - The reference is inside of a loop.
|
||||
* - The reference is inside of a function scope which is different from
|
||||
* the declaration.
|
||||
* @param ref A reference to check.
|
||||
* @param prevRhsNode The previous RHS node.
|
||||
* @returns The RHS node or null.
|
||||
*/
|
||||
function getRhsNode(ref, prevRhsNode) {
|
||||
/**
|
||||
* Checks whether the given node is in a loop or not.
|
||||
* @param node The node to check.
|
||||
* @returns `true` if the node is in a loop.
|
||||
*/
|
||||
function isInLoop(node) {
|
||||
let currentNode = node;
|
||||
while (currentNode) {
|
||||
if (utils_1.ASTUtils.isFunction(currentNode)) {
|
||||
break;
|
||||
}
|
||||
if (utils_1.ASTUtils.isLoop(currentNode)) {
|
||||
return true;
|
||||
}
|
||||
currentNode = currentNode.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const id = ref.identifier;
|
||||
const parent = id.parent;
|
||||
const refScope = ref.from.variableScope;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const varScope = ref.resolved.scope.variableScope;
|
||||
const canBeUsedLater = refScope !== varScope || isInLoop(id);
|
||||
/*
|
||||
* Inherits the previous node if this reference is in the node.
|
||||
* This is for `a = a + a`-like code.
|
||||
*/
|
||||
if (prevRhsNode && isInside(id, prevRhsNode)) {
|
||||
return prevRhsNode;
|
||||
}
|
||||
if (parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression &&
|
||||
isUnusedExpression(parent) &&
|
||||
id === parent.left &&
|
||||
!canBeUsedLater) {
|
||||
return parent.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Checks whether a given reference is a read to update itself or not.
|
||||
* @param ref A reference to check.
|
||||
* @param rhsNode The RHS node of the previous assignment.
|
||||
* @returns The reference is a read to update itself.
|
||||
*/
|
||||
function isReadForItself(ref, rhsNode) {
|
||||
/**
|
||||
* Checks whether a given Identifier node exists inside of a function node which can be used later.
|
||||
*
|
||||
* "can be used later" means:
|
||||
* - the function is assigned to a variable.
|
||||
* - the function is bound to a property and the object can be used later.
|
||||
* - the function is bound as an argument of a function call.
|
||||
*
|
||||
* If a reference exists in a function which can be used later, the reference is read when the function is called.
|
||||
* @param id An Identifier node to check.
|
||||
* @param rhsNode The RHS node of the previous assignment.
|
||||
* @returns `true` if the `id` node exists inside of a function node which can be used later.
|
||||
*/
|
||||
function isInsideOfStorableFunction(id, rhsNode) {
|
||||
/**
|
||||
* Finds a function node from ancestors of a node.
|
||||
* @param node A start node to find.
|
||||
* @returns A found function node.
|
||||
*/
|
||||
function getUpperFunction(node) {
|
||||
let currentNode = node;
|
||||
while (currentNode) {
|
||||
if (utils_1.ASTUtils.isFunction(currentNode)) {
|
||||
return currentNode;
|
||||
}
|
||||
currentNode = currentNode.parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Checks whether a given function node is stored to somewhere or not.
|
||||
* If the function node is stored, the function can be used later.
|
||||
* @param funcNode A function node to check.
|
||||
* @param rhsNode The RHS node of the previous assignment.
|
||||
* @returns `true` if under the following conditions:
|
||||
* - the funcNode is assigned to a variable.
|
||||
* - the funcNode is bound as an argument of a function call.
|
||||
* - the function is bound to a property and the object satisfies above conditions.
|
||||
*/
|
||||
function isStorableFunction(funcNode, rhsNode) {
|
||||
let node = funcNode;
|
||||
let parent = funcNode.parent;
|
||||
while (parent && isInside(parent, rhsNode)) {
|
||||
switch (parent.type) {
|
||||
case utils_1.AST_NODE_TYPES.SequenceExpression:
|
||||
if (parent.expressions[parent.expressions.length - 1] !== node) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case utils_1.AST_NODE_TYPES.CallExpression:
|
||||
case utils_1.AST_NODE_TYPES.NewExpression:
|
||||
return parent.callee !== node;
|
||||
case utils_1.AST_NODE_TYPES.AssignmentExpression:
|
||||
case utils_1.AST_NODE_TYPES.TaggedTemplateExpression:
|
||||
case utils_1.AST_NODE_TYPES.YieldExpression:
|
||||
return true;
|
||||
default:
|
||||
if (parent.type.endsWith('Statement') ||
|
||||
parent.type.endsWith('Declaration')) {
|
||||
/*
|
||||
* If it encountered statements, this is a complex pattern.
|
||||
* Since analyzing complex patterns is hard, this returns `true` to avoid false positive.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
node = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const funcNode = getUpperFunction(id);
|
||||
return (!!funcNode &&
|
||||
isInside(funcNode, rhsNode) &&
|
||||
isStorableFunction(funcNode, rhsNode));
|
||||
}
|
||||
const id = ref.identifier;
|
||||
const parent = id.parent;
|
||||
return (ref.isRead() && // in RHS of an assignment for itself. e.g. `a = a + 1`
|
||||
// self update. e.g. `a += 1`, `a++`
|
||||
((parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression &&
|
||||
!LOGICAL_ASSIGNMENT_OPERATORS.has(parent.operator) &&
|
||||
isUnusedExpression(parent) &&
|
||||
parent.left === id) ||
|
||||
(parent.type === utils_1.AST_NODE_TYPES.UpdateExpression &&
|
||||
isUnusedExpression(parent)) ||
|
||||
(!!rhsNode &&
|
||||
isInside(id, rhsNode) &&
|
||||
!isInsideOfStorableFunction(id, rhsNode))));
|
||||
}
|
||||
const functionNodes = getFunctionDefinitions(variable);
|
||||
const isFunctionDefinition = functionNodes.size > 0;
|
||||
const typeDeclNodes = getTypeDeclarations(variable);
|
||||
const isTypeDecl = typeDeclNodes.size > 0;
|
||||
const moduleDeclNodes = getModuleDeclarations(variable);
|
||||
const isModuleDecl = moduleDeclNodes.size > 0;
|
||||
const enumDeclNodes = getEnumDeclarations(variable);
|
||||
const isEnumDecl = enumDeclNodes.size > 0;
|
||||
const isImportedAsType = variable.defs.every(isTypeImport_1.isTypeImport);
|
||||
let rhsNode = null;
|
||||
return variable.references.some(ref => {
|
||||
const forItself = isReadForItself(ref, rhsNode);
|
||||
rhsNode = getRhsNode(ref, rhsNode);
|
||||
return (ref.isRead() &&
|
||||
!forItself &&
|
||||
!(!isImportedAsType &&
|
||||
((0, referenceContainsTypeQuery_1.referenceContainsTypeQuery)(ref.identifier) ||
|
||||
(0, referenceContainsTypePredicate_1.referenceContainsTypePredicate)(ref.identifier))) &&
|
||||
!(isFunctionDefinition && isSelfReference(ref, functionNodes)) &&
|
||||
!(isTypeDecl && isInsideOneOf(ref, typeDeclNodes)) &&
|
||||
!(isModuleDecl && isSelfReference(ref, moduleDeclNodes)) &&
|
||||
!(isEnumDecl && isSelfReference(ref, enumDeclNodes)));
|
||||
});
|
||||
}
|
||||
//#endregion private helpers
|
||||
/**
|
||||
* Collects the set of unused variables for a given context.
|
||||
*
|
||||
* Due to complexity, this does not take into consideration:
|
||||
* - variables within declaration files
|
||||
* - variables within ambient module declarations
|
||||
*/
|
||||
function collectVariables(context) {
|
||||
return UnusedVarsVisitor.collectUnusedVariables(context.sourceCode.ast, utils_1.ESLintUtils.nullThrows(context.sourceCode.scopeManager, 'Missing required scope manager'));
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"syntaxKind.d.ts","sourceRoot":"","sources":["../../src/enums/syntaxKind.ts"],"names":[],"mappings":"AACA,eAAO,IAAI,UAAU,EAAE,GAAG,CAAC"}
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_wrap_async_generator.js";
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { ESLintScopeVariable } from './ESLintScopeVariable';
|
||||
import type { Variable } from './Variable';
|
||||
export { ESLintScopeVariable } from './ESLintScopeVariable';
|
||||
export { ImplicitLibVariable, type ImplicitLibVariableOptions, type LibDefinition, } from './ImplicitLibVariable';
|
||||
export { Variable } from './Variable';
|
||||
export type ScopeVariable = ESLintScopeVariable | Variable;
|
||||
@@ -0,0 +1,25 @@
|
||||
// file for microbenchmarking
|
||||
|
||||
import { BufferReader } from './buffer-reader'
|
||||
|
||||
const LOOPS = 1000
|
||||
let count = 0
|
||||
const start = performance.now()
|
||||
|
||||
const reader = new BufferReader()
|
||||
const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0])
|
||||
|
||||
const run = () => {
|
||||
if (count > LOOPS) {
|
||||
console.log(performance.now() - start)
|
||||
return
|
||||
}
|
||||
count++
|
||||
for (let i = 0; i < LOOPS; i++) {
|
||||
reader.setBuffer(0, buffer)
|
||||
reader.cstring()
|
||||
}
|
||||
setImmediate(run)
|
||||
}
|
||||
|
||||
run()
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// SEE https://typescript-eslint.io/users/configs
|
||||
//
|
||||
// For developers working in the typescript-eslint monorepo:
|
||||
// You can regenerate it using `pnpm run generate-configs`
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const base_1 = __importDefault(require("./base"));
|
||||
const eslint_recommended_1 = __importDefault(require("./eslint-recommended"));
|
||||
/**
|
||||
* A version of `stylistic` that only contains type-checked rules and disables of any corresponding core ESLint rules.
|
||||
* @see {@link https://typescript-eslint.io/users/configs#stylistic-type-checked-only}
|
||||
*/
|
||||
exports.default = (plugin, parser) => [
|
||||
(0, base_1.default)(plugin, parser),
|
||||
(0, eslint_recommended_1.default)(plugin, parser),
|
||||
{
|
||||
name: 'typescript-eslint/stylistic-type-checked-only',
|
||||
rules: {
|
||||
'dot-notation': 'off',
|
||||
'@typescript-eslint/dot-notation': 'error',
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
|
||||
'@typescript-eslint/prefer-find': 'error',
|
||||
'@typescript-eslint/prefer-includes': 'error',
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
||||
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||
'@typescript-eslint/prefer-regexp-exec': 'error',
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
// THIS CODE WAS AUTOMATICALLY GENERATED
|
||||
// DO NOT EDIT THIS CODE BY HAND
|
||||
// SEE https://typescript-eslint.io/users/configs
|
||||
//
|
||||
// For developers working in the typescript-eslint monorepo:
|
||||
// You can regenerate it using `pnpm run generate-configs`
|
||||
module.exports = {
|
||||
extends: ['./configs/eslintrc/base', './configs/eslintrc/eslint-recommended'],
|
||||
rules: {
|
||||
'dot-notation': 'off',
|
||||
'@typescript-eslint/dot-notation': 'error',
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': 'error',
|
||||
'@typescript-eslint/prefer-find': 'error',
|
||||
'@typescript-eslint/prefer-includes': 'error',
|
||||
'@typescript-eslint/prefer-nullish-coalescing': 'error',
|
||||
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||
'@typescript-eslint/prefer-regexp-exec': 'error',
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': 'error',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Check whether given two characters are a surrogate pair.
|
||||
* @param {number} lead The code of the lead character.
|
||||
* @param {number} tail The code of the tail character.
|
||||
* @returns {boolean} `true` if the character pair is a surrogate pair.
|
||||
*/
|
||||
module.exports = function isSurrogatePair(lead, tail) {
|
||||
return lead >= 0xd800 && lead < 0xdc00 && tail >= 0xdc00 && tail < 0xe000;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
var _is_native_reflect_construct = require("./_is_native_reflect_construct.cjs");
|
||||
var _set_prototype_of = require("./_set_prototype_of.cjs");
|
||||
function _construct(Parent, args, Class) {
|
||||
if (_is_native_reflect_construct._()) exports._ = _construct = Reflect.construct;
|
||||
else {
|
||||
exports._ = _construct = function construct(Parent, args, Class) {
|
||||
var a = [null];
|
||||
a.push.apply(a, args);
|
||||
var Constructor = Function.bind.apply(Parent, a);
|
||||
var instance = new Constructor();
|
||||
|
||||
if (Class) _set_prototype_of._(instance, Class.prototype);
|
||||
|
||||
return instance;
|
||||
};
|
||||
}
|
||||
|
||||
return _construct.apply(null, arguments);
|
||||
}
|
||||
exports._ = _construct;
|
||||
@@ -0,0 +1,48 @@
|
||||
# postgres-interval [](https://travis-ci.org/bendrucker/postgres-interval) [](https://greenkeeper.io/)
|
||||
|
||||
> Parse Postgres interval columns
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save postgres-interval
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var parse = require('postgres-interval')
|
||||
var interval = parse('01:02:03')
|
||||
//=> {hours: 1, minutes: 2, seconds: 3}
|
||||
interval.toPostgres()
|
||||
// 3 seconds 2 minutes 1 hours
|
||||
interval.toISO()
|
||||
// P0Y0M0DT1H2M3S
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
#### `parse(pgInterval)` -> `interval`
|
||||
|
||||
##### pgInterval
|
||||
|
||||
*Required*
|
||||
Type: `string`
|
||||
|
||||
A Postgres interval string.
|
||||
|
||||
#### `interval.toPostgres()` -> `string`
|
||||
|
||||
Returns an interval string. This allows the interval object to be passed into prepared statements.
|
||||
|
||||
#### `interval.toISOString()` -> `string`
|
||||
|
||||
Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string.
|
||||
|
||||
Also available as `interval.toISO()` for backwards compatibility.
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Ben Drucker](http://bendrucker.me)
|
||||
Reference in New Issue
Block a user