corsa-oxlint 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ast_utils.js","names":[],"sources":["../ts/ast_utils.ts"],"sourcesContent":["export function isNodeOfType(\n node: { readonly type?: string } | null | undefined,\n type: string,\n): boolean {\n return node?.type === type;\n}\n\nexport function isIdentifier(\n node: { readonly type?: string; readonly name?: string } | null | undefined,\n name?: string,\n): boolean {\n return node?.type === \"Identifier\" && (name === undefined || node.name === name);\n}\n\nexport const ASTUtils = Object.freeze({\n isIdentifier,\n isNodeOfType,\n});\n"],"mappings":";;;;;;;AAAA,SAAgB,aACd,MACA,MACS;AACT,QAAO,MAAM,SAAS;;AAGxB,SAAgB,aACd,MACA,MACS;AACT,QAAO,MAAM,SAAS,iBAAiB,SAAS,KAAA,KAAa,KAAK,SAAS;;AAG7E,MAAa,WAAW,OAAO,OAAO;CACpC;CACA;CACD,CAAC"}
1
+ {"version":3,"file":"ast_utils.js","names":[],"sources":["../ts/ast_utils.ts"],"sourcesContent":["export function isNodeOfType(\n node: { readonly type?: string } | null | undefined,\n type: string,\n): boolean {\n return node?.type === type;\n}\n\nexport function isIdentifier(\n node: { readonly type?: string; readonly name?: string } | null | undefined,\n name?: string,\n): boolean {\n return node?.type === \"Identifier\" && (name === undefined || node.name === name);\n}\n\nexport const ASTUtils = Object.freeze({\n isIdentifier,\n isNodeOfType,\n});\n"],"mappings":";;;;;;;AAAA,SAAgB,aACd,MACA,MACS;CACT,OAAO,MAAM,SAAS;;AAGxB,SAAgB,aACd,MACA,MACS;CACT,OAAO,MAAM,SAAS,iBAAiB,SAAS,KAAA,KAAa,KAAK,SAAS;;AAG7E,MAAa,WAAW,OAAO,OAAO;CACpC;CACA;CACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"checker.js","names":[],"sources":["../ts/checker.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport { createNodeMaps, toPosition } from \"./node_map\";\nimport { sessionForContext } from \"./registry\";\nimport type {\n ContextWithParserOptions,\n TsgoNode,\n TsgoProgramShape,\n TsgoSignature,\n TsgoSymbol,\n TsgoType,\n TsgoTypeCheckerShape,\n} from \"./types\";\n\nexport function createProgram(\n context: ContextWithParserOptions,\n): TsgoProgramShape & { readonly nodeMaps: ReturnType<typeof createNodeMaps> } {\n const nodeMaps = createNodeMaps(context);\n return {\n nodeMaps,\n getCompilerOptions() {\n return sessionForContext(context).session.getCompilerOptions();\n },\n getCurrentDirectory() {\n return sessionForContext(context).project.rootDir;\n },\n getRootFileNames() {\n return sessionForContext(context).session.getRootFileNames();\n },\n getSourceFile(fileName = context.filename) {\n return { fileName, text: context.sourceCode.text };\n },\n getTypeChecker() {\n return createTypeChecker(context);\n },\n };\n}\n\nexport function createTypeChecker(context: ContextWithParserOptions): TsgoTypeCheckerShape {\n return {\n getTypeAtLocation(node) {\n const lookupNode = nodeForTypeLookup(node);\n return sessionForContext(context).session.getTypeAtPosition(\n filenameFor(context, lookupNode),\n toPosition(lookupNode),\n );\n },\n getContextualType(node) {\n return this.getTypeAtLocation(node);\n },\n getSymbolAtLocation(node) {\n const lookupNode = nodeForTypeLookup(node);\n return sessionForContext(context).session.getSymbolAtPosition(\n filenameFor(context, lookupNode),\n toPosition(lookupNode),\n );\n },\n getTypeOfSymbol(symbol) {\n return sessionForContext(context).session.getTypeOfSymbol(symbol);\n },\n getDeclaredTypeOfSymbol(symbol) {\n return sessionForContext(context).session.getDeclaredTypeOfSymbol(symbol);\n },\n getTypeOfSymbolAtLocation(symbol, node) {\n return this.getTypeAtLocation(node) ?? this.getTypeOfSymbol(symbol);\n },\n typeToString(type, enclosingDeclaration, flags) {\n void enclosingDeclaration;\n return sessionForContext(context).session.typeToString(type, flags);\n },\n getBaseTypeOfLiteralType(type) {\n return sessionForContext(context).session.getBaseTypeOfLiteralType(type);\n },\n getPropertiesOfType(type) {\n return sessionForContext(context).session.getPropertiesOfType(type);\n },\n getSignaturesOfType(type, kind) {\n return sessionForContext(context).session.getSignaturesOfType(type, kind);\n },\n getReturnTypeOfSignature(signature) {\n return sessionForContext(context).session.getReturnTypeOfSignature(signature);\n },\n getTypePredicateOfSignature(signature) {\n return sessionForContext(context).session.getTypePredicateOfSignature(signature);\n },\n getBaseTypes(type) {\n return sessionForContext(context).session.getBaseTypes(type);\n },\n getImplementedTypes(node) {\n return implementedClauseNodes(node)\n .map((clause) => {\n const expression = implementedClauseChildNode(clause, \"expression\") ?? clause;\n const symbol = this.getSymbolAtLocation(expression) ?? this.getSymbolAtLocation(clause);\n return symbol\n ? (this.getDeclaredTypeOfSymbol(symbol) ?? this.getTypeOfSymbol(symbol))\n : (this.getTypeAtLocation(expression) ?? this.getTypeAtLocation(clause));\n })\n .filter((type): type is TsgoType => type !== undefined);\n },\n getTypeArguments(type) {\n return sessionForContext(context).session.getTypeArguments(type);\n },\n };\n}\n\nfunction nodeForTypeLookup(node: Node | TsgoNode): Node | TsgoNode {\n if (\"pos\" in node) {\n return node;\n }\n switch ((node as { readonly type?: string }).type) {\n case \"ClassDeclaration\":\n case \"ClassExpression\":\n return childNode(node, \"id\") ?? node;\n case \"TSPropertySignature\":\n return childNode(node, \"key\") ?? node;\n default:\n return node;\n }\n}\n\nfunction childNode(node: Node, key: string): Node | undefined {\n const value = (node as unknown as Record<string, unknown>)[key];\n if (isNode(value)) {\n return value;\n }\n return undefined;\n}\n\nfunction implementedClauseNodes(node: Node | TsgoNode): readonly Node[] {\n if (\"pos\" in node) {\n return [];\n }\n const clauses = (node as unknown as { readonly implements?: unknown }).implements;\n if (!Array.isArray(clauses)) {\n return [];\n }\n return clauses.filter(isNode);\n}\n\nfunction implementedClauseChildNode(node: Node, key: string): Node | undefined {\n const value = (node as unknown as Record<string, unknown>)[key];\n if (isNode(value)) {\n return value;\n }\n return undefined;\n}\n\nfunction isNode(value: unknown): value is Node {\n return typeof value === \"object\" && value !== null && \"type\" in value && \"range\" in value;\n}\n\nfunction filenameFor(\n context: ContextWithParserOptions,\n node: Node | TsgoNode | TsgoType | TsgoSymbol | TsgoSignature,\n): string {\n if (\"fileName\" in node) {\n return node.fileName;\n }\n return context.filename;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"checker.js","names":[],"sources":["../ts/checker.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport { createNodeMaps, toPosition } from \"./node_map\";\nimport { sessionForContext } from \"./registry\";\nimport type {\n ContextWithParserOptions,\n TsgoNode,\n TsgoProgramShape,\n TsgoSignature,\n TsgoSymbol,\n TsgoType,\n TsgoTypeCheckerShape,\n} from \"./types\";\n\nexport function createProgram(\n context: ContextWithParserOptions,\n): TsgoProgramShape & { readonly nodeMaps: ReturnType<typeof createNodeMaps> } {\n const nodeMaps = createNodeMaps(context);\n return {\n nodeMaps,\n getCompilerOptions() {\n return sessionForContext(context).session.getCompilerOptions();\n },\n getCurrentDirectory() {\n return sessionForContext(context).project.rootDir;\n },\n getRootFileNames() {\n return sessionForContext(context).session.getRootFileNames();\n },\n getSourceFile(fileName = context.filename) {\n return { fileName, text: context.sourceCode.text };\n },\n getTypeChecker() {\n return createTypeChecker(context);\n },\n };\n}\n\nexport function createTypeChecker(context: ContextWithParserOptions): TsgoTypeCheckerShape {\n return {\n getTypeAtLocation(node) {\n const lookupNode = nodeForTypeLookup(node);\n return sessionForContext(context).session.getTypeAtPosition(\n filenameFor(context, lookupNode),\n toPosition(lookupNode),\n );\n },\n getContextualType(node) {\n return this.getTypeAtLocation(node);\n },\n getSymbolAtLocation(node) {\n const lookupNode = nodeForTypeLookup(node);\n return sessionForContext(context).session.getSymbolAtPosition(\n filenameFor(context, lookupNode),\n toPosition(lookupNode),\n );\n },\n getTypeOfSymbol(symbol) {\n return sessionForContext(context).session.getTypeOfSymbol(symbol);\n },\n getDeclaredTypeOfSymbol(symbol) {\n return sessionForContext(context).session.getDeclaredTypeOfSymbol(symbol);\n },\n getTypeOfSymbolAtLocation(symbol, node) {\n return this.getTypeAtLocation(node) ?? this.getTypeOfSymbol(symbol);\n },\n typeToString(type, enclosingDeclaration, flags) {\n void enclosingDeclaration;\n return sessionForContext(context).session.typeToString(type, flags);\n },\n getBaseTypeOfLiteralType(type) {\n return sessionForContext(context).session.getBaseTypeOfLiteralType(type);\n },\n getPropertiesOfType(type) {\n return sessionForContext(context).session.getPropertiesOfType(type);\n },\n getSignaturesOfType(type, kind) {\n return sessionForContext(context).session.getSignaturesOfType(type, kind);\n },\n getReturnTypeOfSignature(signature) {\n return sessionForContext(context).session.getReturnTypeOfSignature(signature);\n },\n getTypePredicateOfSignature(signature) {\n return sessionForContext(context).session.getTypePredicateOfSignature(signature);\n },\n getBaseTypes(type) {\n return sessionForContext(context).session.getBaseTypes(type);\n },\n getImplementedTypes(node) {\n return implementedClauseNodes(node)\n .map((clause) => {\n const expression = implementedClauseChildNode(clause, \"expression\") ?? clause;\n const symbol = this.getSymbolAtLocation(expression) ?? this.getSymbolAtLocation(clause);\n return symbol\n ? (this.getDeclaredTypeOfSymbol(symbol) ?? this.getTypeOfSymbol(symbol))\n : (this.getTypeAtLocation(expression) ?? this.getTypeAtLocation(clause));\n })\n .filter((type): type is TsgoType => type !== undefined);\n },\n getTypeArguments(type) {\n return sessionForContext(context).session.getTypeArguments(type);\n },\n };\n}\n\nfunction nodeForTypeLookup(node: Node | TsgoNode): Node | TsgoNode {\n if (\"pos\" in node) {\n return node;\n }\n switch ((node as { readonly type?: string }).type) {\n case \"ClassDeclaration\":\n case \"ClassExpression\":\n return childNode(node, \"id\") ?? node;\n case \"TSPropertySignature\":\n return childNode(node, \"key\") ?? node;\n default:\n return node;\n }\n}\n\nfunction childNode(node: Node, key: string): Node | undefined {\n const value = (node as unknown as Record<string, unknown>)[key];\n if (isNode(value)) {\n return value;\n }\n return undefined;\n}\n\nfunction implementedClauseNodes(node: Node | TsgoNode): readonly Node[] {\n if (\"pos\" in node) {\n return [];\n }\n const clauses = (node as unknown as { readonly implements?: unknown }).implements;\n if (!Array.isArray(clauses)) {\n return [];\n }\n return clauses.filter(isNode);\n}\n\nfunction implementedClauseChildNode(node: Node, key: string): Node | undefined {\n const value = (node as unknown as Record<string, unknown>)[key];\n if (isNode(value)) {\n return value;\n }\n return undefined;\n}\n\nfunction isNode(value: unknown): value is Node {\n return typeof value === \"object\" && value !== null && \"type\" in value && \"range\" in value;\n}\n\nfunction filenameFor(\n context: ContextWithParserOptions,\n node: Node | TsgoNode | TsgoType | TsgoSymbol | TsgoSignature,\n): string {\n if (\"fileName\" in node) {\n return node.fileName;\n }\n return context.filename;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","names":[],"sources":["../ts/context.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport type {\n ContextWithParserOptions,\n ProjectServiceOptions,\n ResolvedProjectConfig,\n ResolvedRuntimeOptions,\n TypeAwareParserOptions,\n TypescriptOxlintSettings,\n} from \"./types\";\n\nconst DEFAULT_CACHE_LIFETIME_MS = 250;\nconst DEFAULT_PROJECT_PATTERNS = [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"];\nconst DEFAULT_TS_CONFIG = {\n compilerOptions: {\n module: \"esnext\",\n target: \"es2022\",\n strict: true,\n },\n};\n\nexport function defaultCorsaExecutable(rootDir: string, platform = process.platform): string {\n return resolve(rootDir, platform === \"win32\" ? \".cache/tsgo.exe\" : \".cache/tsgo\");\n}\n\nexport const defaultTsgoExecutable = defaultCorsaExecutable;\n\nexport function resolveProjectConfig(context: ContextWithParserOptions): ResolvedProjectConfig {\n const filename = resolve(context.filename);\n const parserOptions = resolveTypeAwareParserOptions(context);\n const rootDir = resolve(parserOptions.tsconfigRootDir ?? context.cwd);\n const runtime = resolveRuntimeOptions(rootDir, parserOptions);\n const configPath =\n resolveExplicitProject(rootDir, parserOptions) ??\n discoverTsconfig(filename, rootDir) ??\n resolveDefaultProject(rootDir, filename, parserOptions.projectService);\n if (!configPath) {\n throw new Error(`corsa-oxlint could not resolve a tsconfig for ${filename}`);\n }\n return { filename, rootDir, configPath, runtime };\n}\n\n/**\n * Resolves the type-aware parser options visible to a rule.\n *\n * Oxlint exposes a fixed `context.languageOptions.parserOptions` object at\n * runtime, so `corsa-oxlint` stores its richer configuration under\n * `settings.typescriptOxlint` and rehydrates the rule-facing parser options\n * shape from there.\n *\n * @example\n * ```ts\n * const parserOptions = resolveTypeAwareParserOptions(context);\n * parserOptions.corsa?.mode;\n * ```\n */\nexport function resolveTypeAwareParserOptions(\n context: ContextWithParserOptions,\n): TypeAwareParserOptions {\n return mergeTypeAwareParserOptions(\n resolveSettingsParserOptions(context.settings?.typescriptOxlint),\n mergeTypeAwareParserOptions(context.parserOptions, context.languageOptions?.parserOptions),\n );\n}\n\nfunction resolveRuntimeOptions(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): ResolvedRuntimeOptions {\n const runtime = parserOptions.corsa ?? parserOptions.tsgo;\n return {\n executable: resolve(\n runtime?.executable ??\n process.env.CORSA_EXECUTABLE ??\n process.env.TSGO_EXECUTABLE ??\n defaultCorsaExecutable(rootDir),\n ),\n cwd: resolve(runtime?.cwd ?? rootDir),\n mode: runtime?.mode ?? \"msgpack\",\n cacheLifetimeMs: runtime?.cacheLifetimeMs ?? DEFAULT_CACHE_LIFETIME_MS,\n };\n}\n\nfunction resolveExplicitProject(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): string | undefined {\n const projects = asArray(parserOptions.project).map((project) => {\n return resolve(rootDir, project);\n });\n return projects.find(existsSync);\n}\n\nfunction discoverTsconfig(filename: string, rootDir: string): string | undefined {\n let current = dirname(filename);\n const boundary = resolve(rootDir);\n while (current.startsWith(boundary)) {\n const candidate = resolve(current, \"tsconfig.json\");\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n return undefined;\n}\n\nfunction resolveDefaultProject(\n rootDir: string,\n filename: string,\n projectService: boolean | ProjectServiceOptions | undefined,\n): string | undefined {\n if (!projectService) {\n return undefined;\n }\n if (projectService !== true && projectService.defaultProject) {\n return resolve(rootDir, projectService.defaultProject);\n }\n if (!matchesDefaultProject(filename, projectService as true | ProjectServiceOptions)) {\n return undefined;\n }\n const id = Buffer.from(filename).toString(\"hex\").slice(0, 24);\n const cacheDir = resolve(rootDir, \".cache/typescript_oxlint/default\");\n const configPath = resolve(cacheDir, `${id}.tsconfig.json`);\n if (!existsSync(configPath)) {\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(\n configPath,\n JSON.stringify(\n {\n ...DEFAULT_TS_CONFIG,\n files: [filename],\n },\n null,\n 2,\n ),\n );\n }\n return configPath;\n}\n\nfunction matchesDefaultProject(\n filename: string,\n projectService: true | ProjectServiceOptions,\n): boolean {\n const patterns =\n (projectService === true ? undefined : projectService.allowDefaultProject) ??\n DEFAULT_PROJECT_PATTERNS;\n return patterns.some((pattern: string) => globMatch(filename, pattern));\n}\n\nfunction globMatch(value: string, pattern: string): boolean {\n const escaped = pattern.replaceAll(\".\", \"\\\\.\").replaceAll(\"*\", \".*\");\n return new RegExp(`${escaped}$`).test(value);\n}\n\nfunction asArray(value: string | string[] | undefined): string[] {\n return value ? (Array.isArray(value) ? value : [value]) : [];\n}\n\nfunction resolveSettingsParserOptions(\n settings: TypescriptOxlintSettings | undefined,\n): TypeAwareParserOptions {\n if (!settings) {\n return {};\n }\n const { parserOptions, ...inline } = settings;\n return mergeTypeAwareParserOptions(inline, parserOptions);\n}\n\nexport function mergeTypeAwareParserOptions(\n base: TypeAwareParserOptions | undefined,\n override: TypeAwareParserOptions | undefined,\n): TypeAwareParserOptions {\n if (!base) {\n return normalizeTypeAwareParserOptions(override ?? {});\n }\n if (!override) {\n return normalizeTypeAwareParserOptions(base);\n }\n const runtime = {\n ...(base.corsa ?? base.tsgo),\n ...(override.corsa ?? override.tsgo),\n };\n return {\n ...base,\n ...override,\n project: override.project ?? base.project,\n projectService: mergeProjectService(base.projectService, override.projectService),\n tsconfigRootDir: override.tsconfigRootDir ?? base.tsconfigRootDir,\n ...(Object.keys(runtime).length > 0 ? { corsa: runtime, tsgo: runtime } : {}),\n };\n}\n\nfunction normalizeTypeAwareParserOptions(options: TypeAwareParserOptions): TypeAwareParserOptions {\n const runtime = options.corsa ?? options.tsgo;\n if (!runtime) {\n return options;\n }\n return {\n ...options,\n corsa: runtime,\n tsgo: runtime,\n };\n}\n\nfunction mergeProjectService(\n base: boolean | ProjectServiceOptions | undefined,\n override: boolean | ProjectServiceOptions | undefined,\n): boolean | ProjectServiceOptions | undefined {\n if (override === undefined) {\n return base;\n }\n if (typeof override === \"boolean\") {\n return override;\n }\n if (base === undefined || typeof base === \"boolean\") {\n return override;\n }\n return {\n ...base,\n ...override,\n allowDefaultProject: override.allowDefaultProject ?? base.allowDefaultProject,\n defaultProject: override.defaultProject ?? base.defaultProject,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"context.js","names":[],"sources":["../ts/context.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\n\nimport type {\n ContextWithParserOptions,\n ProjectServiceOptions,\n ResolvedProjectConfig,\n ResolvedRuntimeOptions,\n TypeAwareParserOptions,\n TypescriptOxlintSettings,\n} from \"./types\";\n\nconst DEFAULT_CACHE_LIFETIME_MS = 250;\nconst DEFAULT_PROJECT_PATTERNS = [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"];\nconst DEFAULT_TS_CONFIG = {\n compilerOptions: {\n module: \"esnext\",\n target: \"es2022\",\n strict: true,\n },\n};\n\nexport function defaultCorsaExecutable(rootDir: string, platform = process.platform): string {\n return resolve(rootDir, platform === \"win32\" ? \".cache/tsgo.exe\" : \".cache/tsgo\");\n}\n\nexport const defaultTsgoExecutable = defaultCorsaExecutable;\n\nexport function resolveProjectConfig(context: ContextWithParserOptions): ResolvedProjectConfig {\n const filename = resolve(context.filename);\n const parserOptions = resolveTypeAwareParserOptions(context);\n const rootDir = resolve(parserOptions.tsconfigRootDir ?? context.cwd);\n const runtime = resolveRuntimeOptions(rootDir, parserOptions);\n const configPath =\n resolveExplicitProject(rootDir, parserOptions) ??\n discoverTsconfig(filename, rootDir) ??\n resolveDefaultProject(rootDir, filename, parserOptions.projectService);\n if (!configPath) {\n throw new Error(`corsa-oxlint could not resolve a tsconfig for ${filename}`);\n }\n return { filename, rootDir, configPath, runtime };\n}\n\n/**\n * Resolves the type-aware parser options visible to a rule.\n *\n * Oxlint exposes a fixed `context.languageOptions.parserOptions` object at\n * runtime, so `corsa-oxlint` stores its richer configuration under\n * `settings.typescriptOxlint` and rehydrates the rule-facing parser options\n * shape from there.\n *\n * @example\n * ```ts\n * const parserOptions = resolveTypeAwareParserOptions(context);\n * parserOptions.corsa?.mode;\n * ```\n */\nexport function resolveTypeAwareParserOptions(\n context: ContextWithParserOptions,\n): TypeAwareParserOptions {\n return mergeTypeAwareParserOptions(\n resolveSettingsParserOptions(context.settings?.typescriptOxlint),\n mergeTypeAwareParserOptions(context.parserOptions, context.languageOptions?.parserOptions),\n );\n}\n\nfunction resolveRuntimeOptions(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): ResolvedRuntimeOptions {\n const runtime = parserOptions.corsa ?? parserOptions.tsgo;\n return {\n executable: resolve(\n runtime?.executable ??\n process.env.CORSA_EXECUTABLE ??\n process.env.TSGO_EXECUTABLE ??\n defaultCorsaExecutable(rootDir),\n ),\n cwd: resolve(runtime?.cwd ?? rootDir),\n mode: runtime?.mode ?? \"msgpack\",\n cacheLifetimeMs: runtime?.cacheLifetimeMs ?? DEFAULT_CACHE_LIFETIME_MS,\n };\n}\n\nfunction resolveExplicitProject(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): string | undefined {\n const projects = asArray(parserOptions.project).map((project) => {\n return resolve(rootDir, project);\n });\n return projects.find(existsSync);\n}\n\nfunction discoverTsconfig(filename: string, rootDir: string): string | undefined {\n let current = dirname(filename);\n const boundary = resolve(rootDir);\n while (current.startsWith(boundary)) {\n const candidate = resolve(current, \"tsconfig.json\");\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n return undefined;\n}\n\nfunction resolveDefaultProject(\n rootDir: string,\n filename: string,\n projectService: boolean | ProjectServiceOptions | undefined,\n): string | undefined {\n if (!projectService) {\n return undefined;\n }\n if (projectService !== true && projectService.defaultProject) {\n return resolve(rootDir, projectService.defaultProject);\n }\n if (!matchesDefaultProject(filename, projectService as true | ProjectServiceOptions)) {\n return undefined;\n }\n const id = Buffer.from(filename).toString(\"hex\").slice(0, 24);\n const cacheDir = resolve(rootDir, \".cache/typescript_oxlint/default\");\n const configPath = resolve(cacheDir, `${id}.tsconfig.json`);\n if (!existsSync(configPath)) {\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(\n configPath,\n JSON.stringify(\n {\n ...DEFAULT_TS_CONFIG,\n files: [filename],\n },\n null,\n 2,\n ),\n );\n }\n return configPath;\n}\n\nfunction matchesDefaultProject(\n filename: string,\n projectService: true | ProjectServiceOptions,\n): boolean {\n const patterns =\n (projectService === true ? undefined : projectService.allowDefaultProject) ??\n DEFAULT_PROJECT_PATTERNS;\n return patterns.some((pattern: string) => globMatch(filename, pattern));\n}\n\nfunction globMatch(value: string, pattern: string): boolean {\n const escaped = pattern.replaceAll(\".\", \"\\\\.\").replaceAll(\"*\", \".*\");\n return new RegExp(`${escaped}$`).test(value);\n}\n\nfunction asArray(value: string | string[] | undefined): string[] {\n return value ? (Array.isArray(value) ? value : [value]) : [];\n}\n\nfunction resolveSettingsParserOptions(\n settings: TypescriptOxlintSettings | undefined,\n): TypeAwareParserOptions {\n if (!settings) {\n return {};\n }\n const { parserOptions, ...inline } = settings;\n return mergeTypeAwareParserOptions(inline, parserOptions);\n}\n\nexport function mergeTypeAwareParserOptions(\n base: TypeAwareParserOptions | undefined,\n override: TypeAwareParserOptions | undefined,\n): TypeAwareParserOptions {\n if (!base) {\n return normalizeTypeAwareParserOptions(override ?? {});\n }\n if (!override) {\n return normalizeTypeAwareParserOptions(base);\n }\n const runtime = {\n ...(base.corsa ?? base.tsgo),\n ...(override.corsa ?? override.tsgo),\n };\n return {\n ...base,\n ...override,\n project: override.project ?? base.project,\n projectService: mergeProjectService(base.projectService, override.projectService),\n tsconfigRootDir: override.tsconfigRootDir ?? base.tsconfigRootDir,\n ...(Object.keys(runtime).length > 0 ? { corsa: runtime, tsgo: runtime } : {}),\n };\n}\n\nfunction normalizeTypeAwareParserOptions(options: TypeAwareParserOptions): TypeAwareParserOptions {\n const runtime = options.corsa ?? options.tsgo;\n if (!runtime) {\n return options;\n }\n return {\n ...options,\n corsa: runtime,\n tsgo: runtime,\n };\n}\n\nfunction mergeProjectService(\n base: boolean | ProjectServiceOptions | undefined,\n override: boolean | ProjectServiceOptions | undefined,\n): boolean | ProjectServiceOptions | undefined {\n if (override === undefined) {\n return base;\n }\n if (typeof override === \"boolean\") {\n return override;\n }\n if (base === undefined || typeof base === \"boolean\") {\n return override;\n }\n return {\n ...base,\n ...override,\n allowDefaultProject: override.allowDefaultProject ?? base.allowDefaultProject,\n defaultProject: override.defaultProject ?? base.defaultProject,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"json_schema.js","names":[],"sources":["../ts/json_schema.ts"],"sourcesContent":["export type JSONSchema4 = Record<string, unknown>;\n\nexport function tupleSchema(...items: readonly JSONSchema4[]): JSONSchema4 {\n return {\n items,\n type: \"array\",\n };\n}\n\nexport const JSONSchema = Object.freeze({\n tupleSchema,\n});\n"],"mappings":";;;;;;AAEA,SAAgB,YAAY,GAAG,OAA4C;AACzE,QAAO;EACL;EACA,MAAM;EACP;;AAGH,MAAa,aAAa,OAAO,OAAO,EACtC,aACD,CAAC"}
1
+ {"version":3,"file":"json_schema.js","names":[],"sources":["../ts/json_schema.ts"],"sourcesContent":["export type JSONSchema4 = Record<string, unknown>;\n\nexport function tupleSchema(...items: readonly JSONSchema4[]): JSONSchema4 {\n return {\n items,\n type: \"array\",\n };\n}\n\nexport const JSONSchema = Object.freeze({\n tupleSchema,\n});\n"],"mappings":";;;;;;AAEA,SAAgB,YAAY,GAAG,OAA4C;CACzE,OAAO;EACL;EACA,MAAM;EACP;;AAGH,MAAa,aAAa,OAAO,OAAO,EACtC,aACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"node_map.js","names":[],"sources":["../ts/node_map.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport type { ContextWithParserOptions, TsgoNode } from \"./types\";\n\nconst estreeToTsgo = new WeakMap<object, TsgoNode>();\nconst tsgoToEstree = new WeakMap<object, Node>();\n\nexport function createNodeMaps(context: ContextWithParserOptions): {\n esTreeNodeToTSNodeMap: {\n get(node: Node): TsgoNode;\n has(node: Node): boolean;\n };\n tsNodeToESTreeNodeMap: {\n get(node: TsgoNode): Node;\n has(node: TsgoNode): boolean;\n };\n} {\n return {\n esTreeNodeToTSNodeMap: {\n get(node) {\n let current = estreeToTsgo.get(node);\n if (!current) {\n current = createTsgoNode(context.filename, node);\n estreeToTsgo.set(node, current);\n tsgoToEstree.set(current, node);\n }\n return current;\n },\n has(node) {\n return estreeToTsgo.has(node);\n },\n },\n tsNodeToESTreeNodeMap: {\n get(node) {\n const value = tsgoToEstree.get(node);\n if (!value) {\n throw new Error(\"corsa-oxlint could not map tsgo node back to ESTree\");\n }\n return value;\n },\n has(node) {\n return tsgoToEstree.has(node);\n },\n },\n };\n}\n\nexport function toPosition(node: Node | TsgoNode): number {\n return \"pos\" in node ? node.pos : assertRange(node)[0];\n}\n\nfunction createTsgoNode(fileName: string, node: Node): TsgoNode {\n const [pos, end] = assertRange(node);\n return {\n fileName,\n pos,\n end,\n range: [pos, end],\n };\n}\n\nfunction assertRange(node: Node): readonly [number, number] {\n const range = (node as Node & { range?: readonly [number, number] }).range;\n if (!range) {\n throw new Error(\"corsa-oxlint requires ESTree nodes with range data\");\n }\n return range;\n}\n"],"mappings":";AAIA,MAAM,+BAAe,IAAI,SAA2B;AACpD,MAAM,+BAAe,IAAI,SAAuB;AAEhD,SAAgB,eAAe,SAS7B;AACA,QAAO;EACL,uBAAuB;GACrB,IAAI,MAAM;IACR,IAAI,UAAU,aAAa,IAAI,KAAK;AACpC,QAAI,CAAC,SAAS;AACZ,eAAU,eAAe,QAAQ,UAAU,KAAK;AAChD,kBAAa,IAAI,MAAM,QAAQ;AAC/B,kBAAa,IAAI,SAAS,KAAK;;AAEjC,WAAO;;GAET,IAAI,MAAM;AACR,WAAO,aAAa,IAAI,KAAK;;GAEhC;EACD,uBAAuB;GACrB,IAAI,MAAM;IACR,MAAM,QAAQ,aAAa,IAAI,KAAK;AACpC,QAAI,CAAC,MACH,OAAM,IAAI,MAAM,sDAAsD;AAExE,WAAO;;GAET,IAAI,MAAM;AACR,WAAO,aAAa,IAAI,KAAK;;GAEhC;EACF;;AAGH,SAAgB,WAAW,MAA+B;AACxD,QAAO,SAAS,OAAO,KAAK,MAAM,YAAY,KAAK,CAAC;;AAGtD,SAAS,eAAe,UAAkB,MAAsB;CAC9D,MAAM,CAAC,KAAK,OAAO,YAAY,KAAK;AACpC,QAAO;EACL;EACA;EACA;EACA,OAAO,CAAC,KAAK,IAAI;EAClB;;AAGH,SAAS,YAAY,MAAuC;CAC1D,MAAM,QAAS,KAAsD;AACrE,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,qDAAqD;AAEvE,QAAO"}
1
+ {"version":3,"file":"node_map.js","names":[],"sources":["../ts/node_map.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport type { ContextWithParserOptions, TsgoNode } from \"./types\";\n\nconst estreeToTsgo = new WeakMap<object, TsgoNode>();\nconst tsgoToEstree = new WeakMap<object, Node>();\n\nexport function createNodeMaps(context: ContextWithParserOptions): {\n esTreeNodeToTSNodeMap: {\n get(node: Node): TsgoNode;\n has(node: Node): boolean;\n };\n tsNodeToESTreeNodeMap: {\n get(node: TsgoNode): Node;\n has(node: TsgoNode): boolean;\n };\n} {\n return {\n esTreeNodeToTSNodeMap: {\n get(node) {\n let current = estreeToTsgo.get(node);\n if (!current) {\n current = createTsgoNode(context.filename, node);\n estreeToTsgo.set(node, current);\n tsgoToEstree.set(current, node);\n }\n return current;\n },\n has(node) {\n return estreeToTsgo.has(node);\n },\n },\n tsNodeToESTreeNodeMap: {\n get(node) {\n const value = tsgoToEstree.get(node);\n if (!value) {\n throw new Error(\"corsa-oxlint could not map tsgo node back to ESTree\");\n }\n return value;\n },\n has(node) {\n return tsgoToEstree.has(node);\n },\n },\n };\n}\n\nexport function toPosition(node: Node | TsgoNode): number {\n return \"pos\" in node ? node.pos : assertRange(node)[0];\n}\n\nfunction createTsgoNode(fileName: string, node: Node): TsgoNode {\n const [pos, end] = assertRange(node);\n return {\n fileName,\n pos,\n end,\n range: [pos, end],\n };\n}\n\nfunction assertRange(node: Node): readonly [number, number] {\n const range = (node as Node & { range?: readonly [number, number] }).range;\n if (!range) {\n throw new Error(\"corsa-oxlint requires ESTree nodes with range data\");\n }\n return range;\n}\n"],"mappings":";AAIA,MAAM,+BAAe,IAAI,SAA2B;AACpD,MAAM,+BAAe,IAAI,SAAuB;AAEhD,SAAgB,eAAe,SAS7B;CACA,OAAO;EACL,uBAAuB;GACrB,IAAI,MAAM;IACR,IAAI,UAAU,aAAa,IAAI,KAAK;IACpC,IAAI,CAAC,SAAS;KACZ,UAAU,eAAe,QAAQ,UAAU,KAAK;KAChD,aAAa,IAAI,MAAM,QAAQ;KAC/B,aAAa,IAAI,SAAS,KAAK;;IAEjC,OAAO;;GAET,IAAI,MAAM;IACR,OAAO,aAAa,IAAI,KAAK;;GAEhC;EACD,uBAAuB;GACrB,IAAI,MAAM;IACR,MAAM,QAAQ,aAAa,IAAI,KAAK;IACpC,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,sDAAsD;IAExE,OAAO;;GAET,IAAI,MAAM;IACR,OAAO,aAAa,IAAI,KAAK;;GAEhC;EACF;;AAGH,SAAgB,WAAW,MAA+B;CACxD,OAAO,SAAS,OAAO,KAAK,MAAM,YAAY,KAAK,CAAC;;AAGtD,SAAS,eAAe,UAAkB,MAAsB;CAC9D,MAAM,CAAC,KAAK,OAAO,YAAY,KAAK;CACpC,OAAO;EACL;EACA;EACA;EACA,OAAO,CAAC,KAAK,IAAI;EAClB;;AAGH,SAAS,YAAY,MAAuC;CAC1D,MAAM,QAAS,KAAsD;CACrE,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,qDAAqD;CAEvE,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"oxlint_compat.js","names":[],"sources":["../ts/oxlint_compat.ts"],"sourcesContent":["export const oxlintCompat = Object.freeze({\n config(...configs: readonly unknown[]) {\n return configs.flat();\n },\n configs: Object.freeze({}),\n parser: Object.freeze({\n meta: {\n name: \"oxlint-plugin-corsa/parser\",\n version: \"0.1.0\",\n },\n parse() {\n throw new Error(\n \"oxlint-plugin-corsa relies on oxlint for parsing; use it as a JS plugin package instead of a standalone parser\",\n );\n },\n }),\n plugin: Object.freeze({\n configs: Object.freeze({}),\n rules: Object.freeze({}),\n }),\n});\n"],"mappings":";;;AAAA,MAAa,eAAe,OAAO,OAAO;CACxC,OAAO,GAAG,SAA6B;AACrC,SAAO,QAAQ,MAAM;;CAEvB,SAAS,OAAO,OAAO,EAAE,CAAC;CAC1B,QAAQ,OAAO,OAAO;EACpB,MAAM;GACJ,MAAM;GACN,SAAS;GACV;EACD,QAAQ;AACN,SAAM,IAAI,MACR,iHACD;;EAEJ,CAAC;CACF,QAAQ,OAAO,OAAO;EACpB,SAAS,OAAO,OAAO,EAAE,CAAC;EAC1B,OAAO,OAAO,OAAO,EAAE,CAAC;EACzB,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"oxlint_compat.js","names":[],"sources":["../ts/oxlint_compat.ts"],"sourcesContent":["export const oxlintCompat = Object.freeze({\n config(...configs: readonly unknown[]) {\n return configs.flat();\n },\n configs: Object.freeze({}),\n parser: Object.freeze({\n meta: {\n name: \"oxlint-plugin-corsa/parser\",\n version: \"0.1.0\",\n },\n parse() {\n throw new Error(\n \"oxlint-plugin-corsa relies on oxlint for parsing; use it as a JS plugin package instead of a standalone parser\",\n );\n },\n }),\n plugin: Object.freeze({\n configs: Object.freeze({}),\n rules: Object.freeze({}),\n }),\n});\n"],"mappings":";;;AAAA,MAAa,eAAe,OAAO,OAAO;CACxC,OAAO,GAAG,SAA6B;EACrC,OAAO,QAAQ,MAAM;;CAEvB,SAAS,OAAO,OAAO,EAAE,CAAC;CAC1B,QAAQ,OAAO,OAAO;EACpB,MAAM;GACJ,MAAM;GACN,SAAS;GACV;EACD,QAAQ;GACN,MAAM,IAAI,MACR,iHACD;;EAEJ,CAAC;CACF,QAAQ,OAAO,OAAO;EACpB,SAAS,OAAO,OAAO,EAAE,CAAC;EAC1B,OAAO,OAAO,OAAO,EAAE,CAAC;EACzB,CAAC;CACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"oxlint_utils.js","names":[],"sources":["../ts/oxlint_utils.ts"],"sourcesContent":["import type { Rule, RuleMeta, Visitor } from \"@oxlint/plugins\";\n\nimport { getParserServices } from \"./parser_services\";\nimport { decorateRule } from \"./plugin\";\nimport type { ContextWithParserOptions } from \"./types\";\n\nexport type RuleCreatorRule<\n TOptions extends readonly unknown[] = readonly unknown[],\n TMessageIds extends string = string,\n> = {\n readonly name: string;\n readonly meta: RuleMeta & {\n readonly messages?: Record<TMessageIds, string>;\n };\n readonly defaultOptions?: TOptions;\n readonly create: (context: ContextWithParserOptions) => Visitor;\n};\n\nexport type RuleCreatorCreatedRule<TRule extends RuleCreatorRule> = Omit<\n TRule,\n \"defaultOptions\" | \"meta\"\n> & {\n readonly defaultOptions: TRule extends { readonly defaultOptions: infer TOptions }\n ? TOptions\n : readonly [];\n readonly meta: TRule[\"meta\"] & {\n readonly docs: NonNullable<TRule[\"meta\"][\"docs\"]> & {\n readonly url: string;\n };\n };\n} & Rule &\n Record<string, unknown>;\n\nexport type RuleCreatorFactory = <TRule extends RuleCreatorRule>(\n rule: TRule,\n) => RuleCreatorCreatedRule<TRule>;\n\n/**\n * Self-hosted type-aware utilities for Oxlint rules backed by tsgo.\n */\nexport const OxlintUtils = Object.freeze({\n RuleCreator(urlCreator: (ruleName: string) => string): RuleCreatorFactory {\n return ((rule) => {\n const docs = rule.meta?.docs;\n return decorateRule({\n ...rule,\n meta: {\n ...rule.meta,\n docs: {\n ...docs,\n url: urlCreator(rule.name),\n },\n },\n defaultOptions: rule.defaultOptions ?? [],\n } as unknown as Rule) as RuleCreatorCreatedRule<typeof rule>;\n }) as RuleCreatorFactory;\n },\n getParserServices(context: ContextWithParserOptions, allowWithoutFullTypeInformation = false) {\n return getParserServices(context, allowWithoutFullTypeInformation);\n },\n});\n\nexport const RuleCreator = OxlintUtils.RuleCreator;\nexport { getParserServices } from \"./parser_services\";\n\nexport function applyDefault<\n Values extends readonly unknown[],\n Defaults extends readonly unknown[],\n>(values: Values | undefined, defaults: Defaults): readonly unknown[] {\n return deepMerge(defaults, values ?? []) as readonly unknown[];\n}\n\nexport function deepMerge<T>(base: T, override: unknown): T {\n if (Array.isArray(base) && Array.isArray(override)) {\n return base.map((value, index) => deepMerge(value, override[index])) as unknown as T;\n }\n if (isObject(base) && isObject(override)) {\n return Object.fromEntries(\n [...new Set([...Object.keys(base), ...Object.keys(override)])].map((key) => [\n key,\n deepMerge((base as any)[key], (override as any)[key]),\n ]),\n ) as T;\n }\n return (override ?? base) as T;\n}\n\nexport function nullThrows<T>(\n value: T | null | undefined,\n message = \"Expected value to be present\",\n): T {\n if (value == null) {\n throw new Error(message);\n }\n return value;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":";;;;;;AAwCA,MAAa,cAAc,OAAO,OAAO;CACvC,YAAY,YAA8D;AACxE,WAAS,SAAS;GAChB,MAAM,OAAO,KAAK,MAAM;AACxB,UAAO,aAAa;IAClB,GAAG;IACH,MAAM;KACJ,GAAG,KAAK;KACR,MAAM;MACJ,GAAG;MACH,KAAK,WAAW,KAAK,KAAK;MAC3B;KACF;IACD,gBAAgB,KAAK,kBAAkB,EAAE;IAC1C,CAAoB;;;CAGzB,kBAAkB,SAAmC,kCAAkC,OAAO;AAC5F,SAAO,kBAAkB,SAAS,gCAAgC;;CAErE,CAAC;AAEF,MAAa,cAAc,YAAY;AAGvC,SAAgB,aAGd,QAA4B,UAAwC;AACpE,QAAO,UAAU,UAAU,UAAU,EAAE,CAAC;;AAG1C,SAAgB,UAAa,MAAS,UAAsB;AAC1D,KAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,SAAS,CAChD,QAAO,KAAK,KAAK,OAAO,UAAU,UAAU,OAAO,SAAS,OAAO,CAAC;AAEtE,KAAI,SAAS,KAAK,IAAI,SAAS,SAAS,CACtC,QAAO,OAAO,YACZ,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,KAAK,EAAE,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAC1E,KACA,UAAW,KAAa,MAAO,SAAiB,KAAK,CACtD,CAAC,CACH;AAEH,QAAQ,YAAY;;AAGtB,SAAgB,WACd,OACA,UAAU,gCACP;AACH,KAAI,SAAS,KACX,OAAM,IAAI,MAAM,QAAQ;AAE1B,QAAO;;AAGT,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
1
+ {"version":3,"file":"oxlint_utils.js","names":[],"sources":["../ts/oxlint_utils.ts"],"sourcesContent":["import type { Rule, RuleMeta, Visitor } from \"@oxlint/plugins\";\n\nimport { getParserServices } from \"./parser_services\";\nimport { decorateRule } from \"./plugin\";\nimport type { ContextWithParserOptions } from \"./types\";\n\nexport type RuleCreatorRule<\n TOptions extends readonly unknown[] = readonly unknown[],\n TMessageIds extends string = string,\n> = {\n readonly name: string;\n readonly meta: RuleMeta & {\n readonly messages?: Record<TMessageIds, string>;\n };\n readonly defaultOptions?: TOptions;\n readonly create: (context: ContextWithParserOptions) => Visitor;\n};\n\nexport type RuleCreatorCreatedRule<TRule extends RuleCreatorRule> = Omit<\n TRule,\n \"defaultOptions\" | \"meta\"\n> & {\n readonly defaultOptions: TRule extends { readonly defaultOptions: infer TOptions }\n ? TOptions\n : readonly [];\n readonly meta: TRule[\"meta\"] & {\n readonly docs: NonNullable<TRule[\"meta\"][\"docs\"]> & {\n readonly url: string;\n };\n };\n} & Rule &\n Record<string, unknown>;\n\nexport type RuleCreatorFactory = <TRule extends RuleCreatorRule>(\n rule: TRule,\n) => RuleCreatorCreatedRule<TRule>;\n\n/**\n * Self-hosted type-aware utilities for Oxlint rules backed by tsgo.\n */\nexport const OxlintUtils = Object.freeze({\n RuleCreator(urlCreator: (ruleName: string) => string): RuleCreatorFactory {\n return ((rule) => {\n const docs = rule.meta?.docs;\n return decorateRule({\n ...rule,\n meta: {\n ...rule.meta,\n docs: {\n ...docs,\n url: urlCreator(rule.name),\n },\n },\n defaultOptions: rule.defaultOptions ?? [],\n } as unknown as Rule) as RuleCreatorCreatedRule<typeof rule>;\n }) as RuleCreatorFactory;\n },\n getParserServices(context: ContextWithParserOptions, allowWithoutFullTypeInformation = false) {\n return getParserServices(context, allowWithoutFullTypeInformation);\n },\n});\n\nexport const RuleCreator = OxlintUtils.RuleCreator;\nexport { getParserServices } from \"./parser_services\";\n\nexport function applyDefault<\n Values extends readonly unknown[],\n Defaults extends readonly unknown[],\n>(values: Values | undefined, defaults: Defaults): readonly unknown[] {\n return deepMerge(defaults, values ?? []) as readonly unknown[];\n}\n\nexport function deepMerge<T>(base: T, override: unknown): T {\n if (Array.isArray(base) && Array.isArray(override)) {\n return base.map((value, index) => deepMerge(value, override[index])) as unknown as T;\n }\n if (isObject(base) && isObject(override)) {\n return Object.fromEntries(\n [...new Set([...Object.keys(base), ...Object.keys(override)])].map((key) => [\n key,\n deepMerge((base as any)[key], (override as any)[key]),\n ]),\n ) as T;\n }\n return (override ?? base) as T;\n}\n\nexport function nullThrows<T>(\n value: T | null | undefined,\n message = \"Expected value to be present\",\n): T {\n if (value == null) {\n throw new Error(message);\n }\n return value;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":";;;;;;AAwCA,MAAa,cAAc,OAAO,OAAO;CACvC,YAAY,YAA8D;EACxE,SAAS,SAAS;GAChB,MAAM,OAAO,KAAK,MAAM;GACxB,OAAO,aAAa;IAClB,GAAG;IACH,MAAM;KACJ,GAAG,KAAK;KACR,MAAM;MACJ,GAAG;MACH,KAAK,WAAW,KAAK,KAAK;MAC3B;KACF;IACD,gBAAgB,KAAK,kBAAkB,EAAE;IAC1C,CAAoB;;;CAGzB,kBAAkB,SAAmC,kCAAkC,OAAO;EAC5F,OAAO,kBAAkB,SAAS,gCAAgC;;CAErE,CAAC;AAEF,MAAa,cAAc,YAAY;AAGvC,SAAgB,aAGd,QAA4B,UAAwC;CACpE,OAAO,UAAU,UAAU,UAAU,EAAE,CAAC;;AAG1C,SAAgB,UAAa,MAAS,UAAsB;CAC1D,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,SAAS,EAChD,OAAO,KAAK,KAAK,OAAO,UAAU,UAAU,OAAO,SAAS,OAAO,CAAC;CAEtE,IAAI,SAAS,KAAK,IAAI,SAAS,SAAS,EACtC,OAAO,OAAO,YACZ,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,KAAK,EAAE,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAC1E,KACA,UAAW,KAAa,MAAO,SAAiB,KAAK,CACtD,CAAC,CACH;CAEH,OAAQ,YAAY;;AAGtB,SAAgB,WACd,OACA,UAAU,gCACP;CACH,IAAI,SAAS,MACX,MAAM,IAAI,MAAM,QAAQ;CAE1B,OAAO;;AAGT,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"parser_services.js","names":[],"sources":["../ts/parser_services.ts"],"sourcesContent":["import { createProgram, createTypeChecker } from \"./checker\";\nimport { createNodeMaps } from \"./node_map\";\nimport type {\n ContextWithParserOptions,\n ParserServices,\n ParserServicesWithTypeInformation,\n} from \"./types\";\n\nconst parserServices = new WeakMap<object, ParserServices>();\n\n/**\n * Returns type-aware parser services backed by tsgo.\n *\n * @example\n * ```ts\n * const services = getParserServices(context);\n * const checker = services.program.getTypeChecker();\n * ```\n */\nexport function getParserServices(\n context: ContextWithParserOptions,\n allowWithoutFullTypeInformation = false,\n): ParserServices {\n const current = parserServices.get(context);\n if (current) {\n return current;\n }\n try {\n const maps = createNodeMaps(context);\n const program = createProgram(context);\n const services: ParserServicesWithTypeInformation = {\n program,\n ...maps,\n hasFullTypeInformation: true,\n getTypeAtLocation(node) {\n return createTypeChecker(context).getTypeAtLocation(node);\n },\n getSymbolAtLocation(node) {\n return createTypeChecker(context).getSymbolAtLocation(node);\n },\n };\n parserServices.set(context, services);\n return services;\n } catch (error) {\n if (!allowWithoutFullTypeInformation) {\n throw error;\n }\n const fallback: ParserServices = {\n program: createProgram(context),\n ...createNodeMaps(context),\n hasFullTypeInformation: false,\n getTypeAtLocation() {\n return undefined;\n },\n getSymbolAtLocation() {\n return undefined;\n },\n };\n parserServices.set(context, fallback);\n return fallback;\n }\n}\n"],"mappings":";;;AAQA,MAAM,iCAAiB,IAAI,SAAiC;;;;;;;;;;AAW5D,SAAgB,kBACd,SACA,kCAAkC,OAClB;CAChB,MAAM,UAAU,eAAe,IAAI,QAAQ;AAC3C,KAAI,QACF,QAAO;AAET,KAAI;EACF,MAAM,OAAO,eAAe,QAAQ;EAEpC,MAAM,WAA8C;GAClD,SAFc,cAAc,QAAQ;GAGpC,GAAG;GACH,wBAAwB;GACxB,kBAAkB,MAAM;AACtB,WAAO,kBAAkB,QAAQ,CAAC,kBAAkB,KAAK;;GAE3D,oBAAoB,MAAM;AACxB,WAAO,kBAAkB,QAAQ,CAAC,oBAAoB,KAAK;;GAE9D;AACD,iBAAe,IAAI,SAAS,SAAS;AACrC,SAAO;UACA,OAAO;AACd,MAAI,CAAC,gCACH,OAAM;EAER,MAAM,WAA2B;GAC/B,SAAS,cAAc,QAAQ;GAC/B,GAAG,eAAe,QAAQ;GAC1B,wBAAwB;GACxB,oBAAoB;GAGpB,sBAAsB;GAGvB;AACD,iBAAe,IAAI,SAAS,SAAS;AACrC,SAAO"}
1
+ {"version":3,"file":"parser_services.js","names":[],"sources":["../ts/parser_services.ts"],"sourcesContent":["import { createProgram, createTypeChecker } from \"./checker\";\nimport { createNodeMaps } from \"./node_map\";\nimport type {\n ContextWithParserOptions,\n ParserServices,\n ParserServicesWithTypeInformation,\n} from \"./types\";\n\nconst parserServices = new WeakMap<object, ParserServices>();\n\n/**\n * Returns type-aware parser services backed by tsgo.\n *\n * @example\n * ```ts\n * const services = getParserServices(context);\n * const checker = services.program.getTypeChecker();\n * ```\n */\nexport function getParserServices(\n context: ContextWithParserOptions,\n allowWithoutFullTypeInformation = false,\n): ParserServices {\n const current = parserServices.get(context);\n if (current) {\n return current;\n }\n try {\n const maps = createNodeMaps(context);\n const program = createProgram(context);\n const services: ParserServicesWithTypeInformation = {\n program,\n ...maps,\n hasFullTypeInformation: true,\n getTypeAtLocation(node) {\n return createTypeChecker(context).getTypeAtLocation(node);\n },\n getSymbolAtLocation(node) {\n return createTypeChecker(context).getSymbolAtLocation(node);\n },\n };\n parserServices.set(context, services);\n return services;\n } catch (error) {\n if (!allowWithoutFullTypeInformation) {\n throw error;\n }\n const fallback: ParserServices = {\n program: createProgram(context),\n ...createNodeMaps(context),\n hasFullTypeInformation: false,\n getTypeAtLocation() {\n return undefined;\n },\n getSymbolAtLocation() {\n return undefined;\n },\n };\n parserServices.set(context, fallback);\n return fallback;\n }\n}\n"],"mappings":";;;AAQA,MAAM,iCAAiB,IAAI,SAAiC;;;;;;;;;;AAW5D,SAAgB,kBACd,SACA,kCAAkC,OAClB;CAChB,MAAM,UAAU,eAAe,IAAI,QAAQ;CAC3C,IAAI,SACF,OAAO;CAET,IAAI;EACF,MAAM,OAAO,eAAe,QAAQ;EAEpC,MAAM,WAA8C;GAClD,SAFc,cAAc,QAErB;GACP,GAAG;GACH,wBAAwB;GACxB,kBAAkB,MAAM;IACtB,OAAO,kBAAkB,QAAQ,CAAC,kBAAkB,KAAK;;GAE3D,oBAAoB,MAAM;IACxB,OAAO,kBAAkB,QAAQ,CAAC,oBAAoB,KAAK;;GAE9D;EACD,eAAe,IAAI,SAAS,SAAS;EACrC,OAAO;UACA,OAAO;EACd,IAAI,CAAC,iCACH,MAAM;EAER,MAAM,WAA2B;GAC/B,SAAS,cAAc,QAAQ;GAC/B,GAAG,eAAe,QAAQ;GAC1B,wBAAwB;GACxB,oBAAoB;GAGpB,sBAAsB;GAGvB;EACD,eAAe,IAAI,SAAS,SAAS;EACrC,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../ts/plugin.ts"],"sourcesContent":["import * as oxlintPluginApi from \"@oxlint/plugins\";\nimport type {\n Context as OxlintContext,\n Plugin as OxlintPlugin,\n Rule as OxlintRule,\n} from \"@oxlint/plugins\";\n\nimport { resolveTypeAwareParserOptions } from \"./context\";\nimport { getParserServices } from \"./parser_services\";\nimport type { ContextWithParserOptions, ParserServices } from \"./types\";\n\ntype PluginShape = OxlintPlugin;\ntype RuleShape = OxlintRule;\nconst defineOxlintPlugin = oxlintPluginApi.definePlugin;\nconst defineOxlintRule = oxlintPluginApi.defineRule;\nconst baseCompatPlugin = Reflect.get(\n oxlintPluginApi as object,\n [\"es\", \"lintCompatPlugin\"].join(\"\"),\n) as typeof oxlintPluginApi.definePlugin;\n\nexport function definePlugin<Plugin extends PluginShape>(plugin: Plugin): Plugin {\n return defineOxlintPlugin({\n ...plugin,\n rules: wrapRules(plugin.rules ?? {}),\n } as OxlintPlugin) as Plugin;\n}\n\n/**\n * Defines a single Oxlint rule with type-aware parser services.\n *\n * @example\n * ```ts\n * export default defineRule({\n * meta: { schema: [], messages: { demo: \"demo\" } },\n * create(context) {\n * const services = context.parserServices;\n * return {};\n * },\n * });\n * ```\n */\nexport function defineRule<Rule extends RuleShape>(rule: Rule): Rule {\n return defineOxlintRule(decorateRule(rule) as OxlintRule) as Rule;\n}\n\nexport function compatPlugin<Plugin extends PluginShape>(plugin: Plugin): Plugin {\n return baseCompatPlugin(definePlugin(plugin)) as Plugin;\n}\n\nexport function decorateRule<Rule extends RuleShape>(rule: Rule): Rule {\n if (rule.create) {\n return {\n ...rule,\n create(context) {\n return rule.create!(decorateContext(context));\n },\n } as Rule;\n }\n if (\"createOnce\" in rule && typeof (rule as any).createOnce === \"function\") {\n return {\n ...rule,\n createOnce(context) {\n return (rule as any).createOnce(decorateContext(context));\n },\n } as Rule;\n }\n return rule;\n}\n\nfunction wrapRules(rules: Record<string, RuleShape>): Record<string, RuleShape> {\n return Object.fromEntries(\n Object.entries(rules).map(([name, rule]) => [name, decorateRule(rule)]),\n );\n}\n\nfunction decorateContext(context: ContextWithParserOptions): ContextWithParserOptions {\n const parserOptions = Object.freeze(resolveTypeAwareParserOptions(context));\n const baseLanguageOptions = context.languageOptions;\n const languageOptions = Object.freeze({\n ...baseLanguageOptions,\n parserOptions,\n });\n return Object.create(context as OxlintContext, {\n languageOptions: {\n configurable: true,\n enumerable: true,\n get() {\n return languageOptions;\n },\n },\n parserOptions: {\n configurable: true,\n enumerable: false,\n get() {\n return parserOptions;\n },\n },\n parserServices: {\n configurable: true,\n enumerable: false,\n get(): ParserServices {\n return getParserServices(context);\n },\n },\n }) as ContextWithParserOptions;\n}\n"],"mappings":";;;;AAaA,MAAM,qBAAqB,gBAAgB;AAC3C,MAAM,mBAAmB,gBAAgB;AACzC,MAAM,mBAAmB,QAAQ,IAC/B,iBACA,CAAC,MAAM,mBAAmB,CAAC,KAAK,GAAG,CACpC;AAED,SAAgB,aAAyC,QAAwB;AAC/E,QAAO,mBAAmB;EACxB,GAAG;EACH,OAAO,UAAU,OAAO,SAAS,EAAE,CAAC;EACrC,CAAiB;;;;;;;;;;;;;;;;AAiBpB,SAAgB,WAAmC,MAAkB;AACnE,QAAO,iBAAiB,aAAa,KAAK,CAAe;;AAG3D,SAAgB,aAAyC,QAAwB;AAC/E,QAAO,iBAAiB,aAAa,OAAO,CAAC;;AAG/C,SAAgB,aAAqC,MAAkB;AACrE,KAAI,KAAK,OACP,QAAO;EACL,GAAG;EACH,OAAO,SAAS;AACd,UAAO,KAAK,OAAQ,gBAAgB,QAAQ,CAAC;;EAEhD;AAEH,KAAI,gBAAgB,QAAQ,OAAQ,KAAa,eAAe,WAC9D,QAAO;EACL,GAAG;EACH,WAAW,SAAS;AAClB,UAAQ,KAAa,WAAW,gBAAgB,QAAQ,CAAC;;EAE5D;AAEH,QAAO;;AAGT,SAAS,UAAU,OAA6D;AAC9E,QAAO,OAAO,YACZ,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,MAAM,aAAa,KAAK,CAAC,CAAC,CACxE;;AAGH,SAAS,gBAAgB,SAA6D;CACpF,MAAM,gBAAgB,OAAO,OAAO,8BAA8B,QAAQ,CAAC;CAC3E,MAAM,sBAAsB,QAAQ;CACpC,MAAM,kBAAkB,OAAO,OAAO;EACpC,GAAG;EACH;EACD,CAAC;AACF,QAAO,OAAO,OAAO,SAA0B;EAC7C,iBAAiB;GACf,cAAc;GACd,YAAY;GACZ,MAAM;AACJ,WAAO;;GAEV;EACD,eAAe;GACb,cAAc;GACd,YAAY;GACZ,MAAM;AACJ,WAAO;;GAEV;EACD,gBAAgB;GACd,cAAc;GACd,YAAY;GACZ,MAAsB;AACpB,WAAO,kBAAkB,QAAQ;;GAEpC;EACF,CAAC"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../ts/plugin.ts"],"sourcesContent":["import * as oxlintPluginApi from \"@oxlint/plugins\";\nimport type {\n Context as OxlintContext,\n Plugin as OxlintPlugin,\n Rule as OxlintRule,\n} from \"@oxlint/plugins\";\n\nimport { resolveTypeAwareParserOptions } from \"./context\";\nimport { getParserServices } from \"./parser_services\";\nimport type { ContextWithParserOptions, ParserServices } from \"./types\";\n\ntype PluginShape = OxlintPlugin;\ntype RuleShape = OxlintRule;\nconst defineOxlintPlugin = oxlintPluginApi.definePlugin;\nconst defineOxlintRule = oxlintPluginApi.defineRule;\nconst baseCompatPlugin = Reflect.get(\n oxlintPluginApi as object,\n [\"es\", \"lintCompatPlugin\"].join(\"\"),\n) as typeof oxlintPluginApi.definePlugin;\n\nexport function definePlugin<Plugin extends PluginShape>(plugin: Plugin): Plugin {\n return defineOxlintPlugin({\n ...plugin,\n rules: wrapRules(plugin.rules ?? {}),\n } as OxlintPlugin) as Plugin;\n}\n\n/**\n * Defines a single Oxlint rule with type-aware parser services.\n *\n * @example\n * ```ts\n * export default defineRule({\n * meta: { schema: [], messages: { demo: \"demo\" } },\n * create(context) {\n * const services = context.parserServices;\n * return {};\n * },\n * });\n * ```\n */\nexport function defineRule<Rule extends RuleShape>(rule: Rule): Rule {\n return defineOxlintRule(decorateRule(rule) as OxlintRule) as Rule;\n}\n\nexport function compatPlugin<Plugin extends PluginShape>(plugin: Plugin): Plugin {\n return baseCompatPlugin(definePlugin(plugin)) as Plugin;\n}\n\nexport function decorateRule<Rule extends RuleShape>(rule: Rule): Rule {\n if (rule.create) {\n return {\n ...rule,\n create(context) {\n return rule.create!(decorateContext(context));\n },\n } as Rule;\n }\n if (\"createOnce\" in rule && typeof (rule as any).createOnce === \"function\") {\n return {\n ...rule,\n createOnce(context) {\n return (rule as any).createOnce(decorateContext(context));\n },\n } as Rule;\n }\n return rule;\n}\n\nfunction wrapRules(rules: Record<string, RuleShape>): Record<string, RuleShape> {\n return Object.fromEntries(\n Object.entries(rules).map(([name, rule]) => [name, decorateRule(rule)]),\n );\n}\n\nfunction decorateContext(context: ContextWithParserOptions): ContextWithParserOptions {\n const parserOptions = Object.freeze(resolveTypeAwareParserOptions(context));\n const baseLanguageOptions = context.languageOptions;\n const languageOptions = Object.freeze({\n ...baseLanguageOptions,\n parserOptions,\n });\n return Object.create(context as OxlintContext, {\n languageOptions: {\n configurable: true,\n enumerable: true,\n get() {\n return languageOptions;\n },\n },\n parserOptions: {\n configurable: true,\n enumerable: false,\n get() {\n return parserOptions;\n },\n },\n parserServices: {\n configurable: true,\n enumerable: false,\n get(): ParserServices {\n return getParserServices(context);\n },\n },\n }) as ContextWithParserOptions;\n}\n"],"mappings":";;;;AAaA,MAAM,qBAAqB,gBAAgB;AAC3C,MAAM,mBAAmB,gBAAgB;AACzC,MAAM,mBAAmB,QAAQ,IAC/B,iBACA,CAAC,MAAM,mBAAmB,CAAC,KAAK,GAAG,CACpC;AAED,SAAgB,aAAyC,QAAwB;CAC/E,OAAO,mBAAmB;EACxB,GAAG;EACH,OAAO,UAAU,OAAO,SAAS,EAAE,CAAC;EACrC,CAAiB;;;;;;;;;;;;;;;;AAiBpB,SAAgB,WAAmC,MAAkB;CACnE,OAAO,iBAAiB,aAAa,KAAK,CAAe;;AAG3D,SAAgB,aAAyC,QAAwB;CAC/E,OAAO,iBAAiB,aAAa,OAAO,CAAC;;AAG/C,SAAgB,aAAqC,MAAkB;CACrE,IAAI,KAAK,QACP,OAAO;EACL,GAAG;EACH,OAAO,SAAS;GACd,OAAO,KAAK,OAAQ,gBAAgB,QAAQ,CAAC;;EAEhD;CAEH,IAAI,gBAAgB,QAAQ,OAAQ,KAAa,eAAe,YAC9D,OAAO;EACL,GAAG;EACH,WAAW,SAAS;GAClB,OAAQ,KAAa,WAAW,gBAAgB,QAAQ,CAAC;;EAE5D;CAEH,OAAO;;AAGT,SAAS,UAAU,OAA6D;CAC9E,OAAO,OAAO,YACZ,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,MAAM,aAAa,KAAK,CAAC,CAAC,CACxE;;AAGH,SAAS,gBAAgB,SAA6D;CACpF,MAAM,gBAAgB,OAAO,OAAO,8BAA8B,QAAQ,CAAC;CAC3E,MAAM,sBAAsB,QAAQ;CACpC,MAAM,kBAAkB,OAAO,OAAO;EACpC,GAAG;EACH;EACD,CAAC;CACF,OAAO,OAAO,OAAO,SAA0B;EAC7C,iBAAiB;GACf,cAAc;GACd,YAAY;GACZ,MAAM;IACJ,OAAO;;GAEV;EACD,eAAe;GACb,cAAc;GACd,YAAY;GACZ,MAAM;IACJ,OAAO;;GAEV;EACD,gBAAgB;GACd,cAAc;GACd,YAAY;GACZ,MAAsB;IACpB,OAAO,kBAAkB,QAAQ;;GAEpC;EACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../ts/registry.ts"],"sourcesContent":["import type { ContextWithParserOptions } from \"./types\";\nimport { resolveProjectConfig } from \"./context\";\nimport { TsgoProjectSession } from \"./session\";\n\nconst sessions = new Map<string, TsgoProjectSession>();\nlet installedExitHook = false;\n\nexport function sessionForContext(context: ContextWithParserOptions): {\n project: ReturnType<typeof resolveProjectConfig>;\n session: TsgoProjectSession;\n} {\n const project = resolveProjectConfig(context);\n const key = [\n project.configPath,\n project.runtime.executable,\n project.runtime.cwd,\n project.runtime.mode,\n ].join(\"::\");\n let session = sessions.get(key);\n if (!session) {\n session = new TsgoProjectSession(project, project.runtime);\n sessions.set(key, session);\n }\n installExitHook();\n return { project, session };\n}\n\nfunction installExitHook(): void {\n if (installedExitHook) {\n return;\n }\n installedExitHook = true;\n process.on(\"exit\", () => {\n for (const session of sessions.values()) {\n session.close();\n }\n });\n}\n"],"mappings":";;;AAIA,MAAM,2BAAW,IAAI,KAAiC;AACtD,IAAI,oBAAoB;AAExB,SAAgB,kBAAkB,SAGhC;CACA,MAAM,UAAU,qBAAqB,QAAQ;CAC7C,MAAM,MAAM;EACV,QAAQ;EACR,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EACjB,CAAC,KAAK,KAAK;CACZ,IAAI,UAAU,SAAS,IAAI,IAAI;AAC/B,KAAI,CAAC,SAAS;AACZ,YAAU,IAAI,mBAAmB,SAAS,QAAQ,QAAQ;AAC1D,WAAS,IAAI,KAAK,QAAQ;;AAE5B,kBAAiB;AACjB,QAAO;EAAE;EAAS;EAAS;;AAG7B,SAAS,kBAAwB;AAC/B,KAAI,kBACF;AAEF,qBAAoB;AACpB,SAAQ,GAAG,cAAc;AACvB,OAAK,MAAM,WAAW,SAAS,QAAQ,CACrC,SAAQ,OAAO;GAEjB"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../ts/registry.ts"],"sourcesContent":["import type { ContextWithParserOptions } from \"./types\";\nimport { resolveProjectConfig } from \"./context\";\nimport { TsgoProjectSession } from \"./session\";\n\nconst sessions = new Map<string, TsgoProjectSession>();\nlet installedExitHook = false;\n\nexport function sessionForContext(context: ContextWithParserOptions): {\n project: ReturnType<typeof resolveProjectConfig>;\n session: TsgoProjectSession;\n} {\n const project = resolveProjectConfig(context);\n const key = [\n project.configPath,\n project.runtime.executable,\n project.runtime.cwd,\n project.runtime.mode,\n ].join(\"::\");\n let session = sessions.get(key);\n if (!session) {\n session = new TsgoProjectSession(project, project.runtime);\n sessions.set(key, session);\n }\n installExitHook();\n return { project, session };\n}\n\nfunction installExitHook(): void {\n if (installedExitHook) {\n return;\n }\n installedExitHook = true;\n process.on(\"exit\", () => {\n for (const session of sessions.values()) {\n session.close();\n }\n });\n}\n"],"mappings":";;;AAIA,MAAM,2BAAW,IAAI,KAAiC;AACtD,IAAI,oBAAoB;AAExB,SAAgB,kBAAkB,SAGhC;CACA,MAAM,UAAU,qBAAqB,QAAQ;CAC7C,MAAM,MAAM;EACV,QAAQ;EACR,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EACjB,CAAC,KAAK,KAAK;CACZ,IAAI,UAAU,SAAS,IAAI,IAAI;CAC/B,IAAI,CAAC,SAAS;EACZ,UAAU,IAAI,mBAAmB,SAAS,QAAQ,QAAQ;EAC1D,SAAS,IAAI,KAAK,QAAQ;;CAE5B,iBAAiB;CACjB,OAAO;EAAE;EAAS;EAAS;;AAG7B,SAAS,kBAAwB;CAC/B,IAAI,mBACF;CAEF,oBAAoB;CACpB,QAAQ,GAAG,cAAc;EACvB,KAAK,MAAM,WAAW,SAAS,QAAQ,EACrC,QAAQ,OAAO;GAEjB"}
@@ -1,9 +1,9 @@
1
- import * as oxlint_plugins_dev0 from "oxlint/plugins-dev";
1
+ import * as _$oxlint_plugins_dev0 from "oxlint/plugins-dev";
2
2
 
3
3
  //#region src/bindings/nodejs/typescript_oxlint/ts/rule_tester.d.ts
4
- type TesterConfig = oxlint_plugins_dev0.RuleTester.Config;
5
- type TestCase = oxlint_plugins_dev0.RuleTester.ValidTestCase & Partial<oxlint_plugins_dev0.RuleTester.InvalidTestCase>;
6
- type TestCases = oxlint_plugins_dev0.RuleTester.TestCases;
4
+ type TesterConfig = _$oxlint_plugins_dev0.RuleTester.Config;
5
+ type TestCase = _$oxlint_plugins_dev0.RuleTester.ValidTestCase & Partial<_$oxlint_plugins_dev0.RuleTester.InvalidTestCase>;
6
+ type TestCases = _$oxlint_plugins_dev0.RuleTester.TestCases;
7
7
  declare class RuleTester {
8
8
  #private;
9
9
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"rule_tester.js","names":["OxlintRuleTester","#inner","#config"],"sources":["../ts/rule_tester.ts"],"sourcesContent":["import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { RuleTester as OxlintRuleTester } from \"oxlint/plugins-dev\";\n\nimport { mergeTypeAwareParserOptions } from \"./context\";\nimport { decorateRule } from \"./plugin\";\nimport type { TypeAwareParserOptions, TypescriptOxlintSettings } from \"./types\";\n\ntype TesterConfig = import(\"oxlint/plugins-dev\").RuleTester.Config;\ntype TestCase = import(\"oxlint/plugins-dev\").RuleTester.ValidTestCase &\n Partial<import(\"oxlint/plugins-dev\").RuleTester.InvalidTestCase>;\ntype TestCases = import(\"oxlint/plugins-dev\").RuleTester.TestCases;\ntype ConfigWithSettings = TesterConfig & {\n settings?: {\n typescriptOxlint?: TypescriptOxlintSettings;\n [key: string]: unknown;\n };\n};\n\nconst cleanupDirs = new Set<string>();\nlet cleanupInstalled = false;\n\nexport class RuleTester {\n /**\n * A thin Oxlint `RuleTester` wrapper that injects\n * `settings.typescriptOxlint`\n * settings, temporary fixtures, and a default project service.\n *\n * @example\n * ```ts\n * const tester = new RuleTester();\n * tester.run(\"demo\", rule, {\n * valid: [{ code: \"const answer = 42;\" }],\n * invalid: [],\n * });\n * ```\n */\n static get describe() {\n return OxlintRuleTester.describe;\n }\n\n static set describe(value) {\n OxlintRuleTester.describe = value;\n }\n\n static get it() {\n return OxlintRuleTester.it;\n }\n\n static set it(value) {\n OxlintRuleTester.it = value;\n }\n\n static only(item: string | TestCase): TestCase {\n return OxlintRuleTester.only(item);\n }\n\n readonly #inner: OxlintRuleTester;\n readonly #config?: TesterConfig;\n\n constructor(config?: TesterConfig) {\n this.#config = config;\n this.#inner = new OxlintRuleTester(config);\n }\n\n run(ruleName: string, rule: Record<string, unknown>, tests: TestCases): void {\n const workspace = mkdtempSync(join(tmpdir(), \"corsa-oxlint-\"));\n registerCleanup(workspace);\n const transformed = {\n valid: tests.valid.map((test) => prepareTestCase(workspace, test, this.#config)),\n invalid: tests.invalid.map((test) => prepareTestCase(workspace, test, this.#config)),\n };\n this.#inner.run(ruleName, decorateRule(rule as never) as never, transformed as TestCases);\n }\n}\n\nfunction prepareTestCase(\n workspace: string,\n test: string | TestCase,\n config: TesterConfig | undefined,\n): string | TestCase {\n if (typeof test === \"string\") {\n const filename = resolve(workspace, \"fixture.ts\");\n writeFixture(filename, test);\n return test;\n }\n const filename = resolve(workspace, test.filename ?? \"fixture.ts\");\n writeFixture(filename, test.code);\n const testerConfig = config as ConfigWithSettings | undefined;\n const baseSettings = testerConfig?.settings?.typescriptOxlint;\n const caseSettings = (\n test.settings as {\n typescriptOxlint?: TypescriptOxlintSettings;\n }\n )?.typescriptOxlint;\n const parserOptions = mergeTypeAwareParserOptions(\n mergeTypeAwareParserOptions(\n mergeTypeAwareParserOptions(\n mergeTypeAwareParserOptions(baseSettings, baseSettings?.parserOptions),\n mergeTypeAwareParserOptions(caseSettings, caseSettings?.parserOptions),\n ),\n {\n tsconfigRootDir: workspace,\n projectService: {\n allowDefaultProject: [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"],\n },\n },\n ),\n mergeTypeAwareParserOptions(\n config?.languageOptions?.parserOptions as TypeAwareParserOptions | undefined,\n test.languageOptions?.parserOptions as TypeAwareParserOptions | undefined,\n ),\n );\n return {\n ...test,\n filename,\n settings: {\n ...testerConfig?.settings,\n ...test.settings,\n typescriptOxlint: {\n ...testerConfig?.settings?.typescriptOxlint,\n ...(test.settings as { typescriptOxlint?: TypescriptOxlintSettings })?.typescriptOxlint,\n parserOptions,\n },\n } as never,\n languageOptions: {\n ...config?.languageOptions,\n ...test.languageOptions,\n parserOptions: {\n ...parserOptions,\n } as never,\n },\n };\n}\n\nfunction writeFixture(filename: string, code: string): void {\n mkdirSync(dirname(filename), { recursive: true });\n writeFileSync(filename, code);\n const configPath = resolve(dirname(filename), \"tsconfig.json\");\n writeFileSync(\n configPath,\n JSON.stringify(\n {\n compilerOptions: {\n module: \"esnext\",\n target: \"es2022\",\n strict: true,\n },\n include: [\"**/*\"],\n },\n null,\n 2,\n ),\n );\n}\n\nfunction registerCleanup(workspace: string): void {\n cleanupDirs.add(workspace);\n if (cleanupInstalled) {\n return;\n }\n cleanupInstalled = true;\n process.on(\"exit\", () => {\n for (const dir of cleanupDirs) {\n rmSync(dir, { force: true, recursive: true });\n }\n });\n}\n"],"mappings":";;;;;;;AAqBA,MAAM,8BAAc,IAAI,KAAa;AACrC,IAAI,mBAAmB;AAEvB,IAAa,aAAb,MAAwB;;;;;;;;;;;;;;;CAetB,WAAW,WAAW;AACpB,SAAOA,aAAiB;;CAG1B,WAAW,SAAS,OAAO;AACzB,eAAiB,WAAW;;CAG9B,WAAW,KAAK;AACd,SAAOA,aAAiB;;CAG1B,WAAW,GAAG,OAAO;AACnB,eAAiB,KAAK;;CAGxB,OAAO,KAAK,MAAmC;AAC7C,SAAOA,aAAiB,KAAK,KAAK;;CAGpC;CACA;CAEA,YAAY,QAAuB;AACjC,QAAA,SAAe;AACf,QAAA,QAAc,IAAIA,aAAiB,OAAO;;CAG5C,IAAI,UAAkB,MAA+B,OAAwB;EAC3E,MAAM,YAAY,YAAY,KAAK,QAAQ,EAAE,gBAAgB,CAAC;AAC9D,kBAAgB,UAAU;EAC1B,MAAM,cAAc;GAClB,OAAO,MAAM,MAAM,KAAK,SAAS,gBAAgB,WAAW,MAAM,MAAA,OAAa,CAAC;GAChF,SAAS,MAAM,QAAQ,KAAK,SAAS,gBAAgB,WAAW,MAAM,MAAA,OAAa,CAAC;GACrF;AACD,QAAA,MAAY,IAAI,UAAU,aAAa,KAAc,EAAW,YAAyB;;;AAI7F,SAAS,gBACP,WACA,MACA,QACmB;AACnB,KAAI,OAAO,SAAS,UAAU;AAE5B,eADiB,QAAQ,WAAW,aAAa,EAC1B,KAAK;AAC5B,SAAO;;CAET,MAAM,WAAW,QAAQ,WAAW,KAAK,YAAY,aAAa;AAClE,cAAa,UAAU,KAAK,KAAK;CACjC,MAAM,eAAe;CACrB,MAAM,eAAe,cAAc,UAAU;CAC7C,MAAM,eACJ,KAAK,UAGJ;CACH,MAAM,gBAAgB,4BACpB,4BACE,4BACE,4BAA4B,cAAc,cAAc,cAAc,EACtE,4BAA4B,cAAc,cAAc,cAAc,CACvE,EACD;EACE,iBAAiB;EACjB,gBAAgB,EACd,qBAAqB;GAAC;GAAQ;GAAS;GAAQ;GAAQ,EACxD;EACF,CACF,EACD,4BACE,QAAQ,iBAAiB,eACzB,KAAK,iBAAiB,cACvB,CACF;AACD,QAAO;EACL,GAAG;EACH;EACA,UAAU;GACR,GAAG,cAAc;GACjB,GAAG,KAAK;GACR,kBAAkB;IAChB,GAAG,cAAc,UAAU;IAC3B,GAAI,KAAK,UAA8D;IACvE;IACD;GACF;EACD,iBAAiB;GACf,GAAG,QAAQ;GACX,GAAG,KAAK;GACR,eAAe,EACb,GAAG,eACJ;GACF;EACF;;AAGH,SAAS,aAAa,UAAkB,MAAoB;AAC1D,WAAU,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AACjD,eAAc,UAAU,KAAK;AAE7B,eADmB,QAAQ,QAAQ,SAAS,EAAE,gBAAgB,EAG5D,KAAK,UACH;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,QAAQ;GACT;EACD,SAAS,CAAC,OAAO;EAClB,EACD,MACA,EACD,CACF;;AAGH,SAAS,gBAAgB,WAAyB;AAChD,aAAY,IAAI,UAAU;AAC1B,KAAI,iBACF;AAEF,oBAAmB;AACnB,SAAQ,GAAG,cAAc;AACvB,OAAK,MAAM,OAAO,YAChB,QAAO,KAAK;GAAE,OAAO;GAAM,WAAW;GAAM,CAAC;GAE/C"}
1
+ {"version":3,"file":"rule_tester.js","names":["OxlintRuleTester","#inner","#config"],"sources":["../ts/rule_tester.ts"],"sourcesContent":["import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { RuleTester as OxlintRuleTester } from \"oxlint/plugins-dev\";\n\nimport { mergeTypeAwareParserOptions } from \"./context\";\nimport { decorateRule } from \"./plugin\";\nimport type { TypeAwareParserOptions, TypescriptOxlintSettings } from \"./types\";\n\ntype TesterConfig = import(\"oxlint/plugins-dev\").RuleTester.Config;\ntype TestCase = import(\"oxlint/plugins-dev\").RuleTester.ValidTestCase &\n Partial<import(\"oxlint/plugins-dev\").RuleTester.InvalidTestCase>;\ntype TestCases = import(\"oxlint/plugins-dev\").RuleTester.TestCases;\ntype ConfigWithSettings = TesterConfig & {\n settings?: {\n typescriptOxlint?: TypescriptOxlintSettings;\n [key: string]: unknown;\n };\n};\n\nconst cleanupDirs = new Set<string>();\nlet cleanupInstalled = false;\n\nexport class RuleTester {\n /**\n * A thin Oxlint `RuleTester` wrapper that injects\n * `settings.typescriptOxlint`\n * settings, temporary fixtures, and a default project service.\n *\n * @example\n * ```ts\n * const tester = new RuleTester();\n * tester.run(\"demo\", rule, {\n * valid: [{ code: \"const answer = 42;\" }],\n * invalid: [],\n * });\n * ```\n */\n static get describe() {\n return OxlintRuleTester.describe;\n }\n\n static set describe(value) {\n OxlintRuleTester.describe = value;\n }\n\n static get it() {\n return OxlintRuleTester.it;\n }\n\n static set it(value) {\n OxlintRuleTester.it = value;\n }\n\n static only(item: string | TestCase): TestCase {\n return OxlintRuleTester.only(item);\n }\n\n readonly #inner: OxlintRuleTester;\n readonly #config?: TesterConfig;\n\n constructor(config?: TesterConfig) {\n this.#config = config;\n this.#inner = new OxlintRuleTester(config);\n }\n\n run(ruleName: string, rule: Record<string, unknown>, tests: TestCases): void {\n const workspace = mkdtempSync(join(tmpdir(), \"corsa-oxlint-\"));\n registerCleanup(workspace);\n const transformed = {\n valid: tests.valid.map((test) => prepareTestCase(workspace, test, this.#config)),\n invalid: tests.invalid.map((test) => prepareTestCase(workspace, test, this.#config)),\n };\n this.#inner.run(ruleName, decorateRule(rule as never) as never, transformed as TestCases);\n }\n}\n\nfunction prepareTestCase(\n workspace: string,\n test: string | TestCase,\n config: TesterConfig | undefined,\n): string | TestCase {\n if (typeof test === \"string\") {\n const filename = resolve(workspace, \"fixture.ts\");\n writeFixture(filename, test);\n return test;\n }\n const filename = resolve(workspace, test.filename ?? \"fixture.ts\");\n writeFixture(filename, test.code);\n const testerConfig = config as ConfigWithSettings | undefined;\n const baseSettings = testerConfig?.settings?.typescriptOxlint;\n const caseSettings = (\n test.settings as {\n typescriptOxlint?: TypescriptOxlintSettings;\n }\n )?.typescriptOxlint;\n const parserOptions = mergeTypeAwareParserOptions(\n mergeTypeAwareParserOptions(\n mergeTypeAwareParserOptions(\n mergeTypeAwareParserOptions(baseSettings, baseSettings?.parserOptions),\n mergeTypeAwareParserOptions(caseSettings, caseSettings?.parserOptions),\n ),\n {\n tsconfigRootDir: workspace,\n projectService: {\n allowDefaultProject: [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"],\n },\n },\n ),\n mergeTypeAwareParserOptions(\n config?.languageOptions?.parserOptions as TypeAwareParserOptions | undefined,\n test.languageOptions?.parserOptions as TypeAwareParserOptions | undefined,\n ),\n );\n return {\n ...test,\n filename,\n settings: {\n ...testerConfig?.settings,\n ...test.settings,\n typescriptOxlint: {\n ...testerConfig?.settings?.typescriptOxlint,\n ...(test.settings as { typescriptOxlint?: TypescriptOxlintSettings })?.typescriptOxlint,\n parserOptions,\n },\n } as never,\n languageOptions: {\n ...config?.languageOptions,\n ...test.languageOptions,\n parserOptions: {\n ...parserOptions,\n } as never,\n },\n };\n}\n\nfunction writeFixture(filename: string, code: string): void {\n mkdirSync(dirname(filename), { recursive: true });\n writeFileSync(filename, code);\n const configPath = resolve(dirname(filename), \"tsconfig.json\");\n writeFileSync(\n configPath,\n JSON.stringify(\n {\n compilerOptions: {\n module: \"esnext\",\n target: \"es2022\",\n strict: true,\n },\n include: [\"**/*\"],\n },\n null,\n 2,\n ),\n );\n}\n\nfunction registerCleanup(workspace: string): void {\n cleanupDirs.add(workspace);\n if (cleanupInstalled) {\n return;\n }\n cleanupInstalled = true;\n process.on(\"exit\", () => {\n for (const dir of cleanupDirs) {\n rmSync(dir, { force: true, recursive: true });\n }\n });\n}\n"],"mappings":";;;;;;;AAqBA,MAAM,8BAAc,IAAI,KAAa;AACrC,IAAI,mBAAmB;AAEvB,IAAa,aAAb,MAAwB;;;;;;;;;;;;;;;CAetB,WAAW,WAAW;EACpB,OAAOA,aAAiB;;CAG1B,WAAW,SAAS,OAAO;EACzB,aAAiB,WAAW;;CAG9B,WAAW,KAAK;EACd,OAAOA,aAAiB;;CAG1B,WAAW,GAAG,OAAO;EACnB,aAAiB,KAAK;;CAGxB,OAAO,KAAK,MAAmC;EAC7C,OAAOA,aAAiB,KAAK,KAAK;;CAGpC;CACA;CAEA,YAAY,QAAuB;EACjC,KAAKE,UAAU;EACf,KAAKD,SAAS,IAAID,aAAiB,OAAO;;CAG5C,IAAI,UAAkB,MAA+B,OAAwB;EAC3E,MAAM,YAAY,YAAY,KAAK,QAAQ,EAAE,gBAAgB,CAAC;EAC9D,gBAAgB,UAAU;EAC1B,MAAM,cAAc;GAClB,OAAO,MAAM,MAAM,KAAK,SAAS,gBAAgB,WAAW,MAAM,KAAKE,QAAQ,CAAC;GAChF,SAAS,MAAM,QAAQ,KAAK,SAAS,gBAAgB,WAAW,MAAM,KAAKA,QAAQ,CAAC;GACrF;EACD,KAAKD,OAAO,IAAI,UAAU,aAAa,KAAc,EAAW,YAAyB;;;AAI7F,SAAS,gBACP,WACA,MACA,QACmB;CACnB,IAAI,OAAO,SAAS,UAAU;EAE5B,aADiB,QAAQ,WAAW,aACf,EAAE,KAAK;EAC5B,OAAO;;CAET,MAAM,WAAW,QAAQ,WAAW,KAAK,YAAY,aAAa;CAClE,aAAa,UAAU,KAAK,KAAK;CACjC,MAAM,eAAe;CACrB,MAAM,eAAe,cAAc,UAAU;CAC7C,MAAM,eACJ,KAAK,UAGJ;CACH,MAAM,gBAAgB,4BACpB,4BACE,4BACE,4BAA4B,cAAc,cAAc,cAAc,EACtE,4BAA4B,cAAc,cAAc,cAAc,CACvE,EACD;EACE,iBAAiB;EACjB,gBAAgB,EACd,qBAAqB;GAAC;GAAQ;GAAS;GAAQ;GAAQ,EACxD;EACF,CACF,EACD,4BACE,QAAQ,iBAAiB,eACzB,KAAK,iBAAiB,cACvB,CACF;CACD,OAAO;EACL,GAAG;EACH;EACA,UAAU;GACR,GAAG,cAAc;GACjB,GAAG,KAAK;GACR,kBAAkB;IAChB,GAAG,cAAc,UAAU;IAC3B,GAAI,KAAK,UAA8D;IACvE;IACD;GACF;EACD,iBAAiB;GACf,GAAG,QAAQ;GACX,GAAG,KAAK;GACR,eAAe,EACb,GAAG,eACJ;GACF;EACF;;AAGH,SAAS,aAAa,UAAkB,MAAoB;CAC1D,UAAU,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;CACjD,cAAc,UAAU,KAAK;CAE7B,cADmB,QAAQ,QAAQ,SAAS,EAAE,gBAElC,EACV,KAAK,UACH;EACE,iBAAiB;GACf,QAAQ;GACR,QAAQ;GACR,QAAQ;GACT;EACD,SAAS,CAAC,OAAO;EAClB,EACD,MACA,EACD,CACF;;AAGH,SAAS,gBAAgB,WAAyB;CAChD,YAAY,IAAI,UAAU;CAC1B,IAAI,kBACF;CAEF,mBAAmB;CACnB,QAAQ,GAAG,cAAc;EACvB,KAAK,MAAM,OAAO,aAChB,OAAO,KAAK;GAAE,OAAO;GAAM,WAAW;GAAM,CAAC;GAE/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ast.js","names":[],"sources":["../../ts/rules/ast.ts"],"sourcesContent":["export function stripChainExpression<Node>(node: Node): Node {\n let current = node as any;\n while (current?.type === \"ChainExpression\") {\n current = current.expression;\n }\n return current as Node;\n}\n\nexport function memberPropertyName(node: unknown): string | undefined {\n const current = stripChainExpression(node as any) as any;\n if (!current || current.type !== \"MemberExpression\") {\n return undefined;\n }\n if (!current.computed && current.property?.type === \"Identifier\") {\n return current.property.name;\n }\n if (current.computed && current.property?.type === \"Literal\") {\n return String(current.property.value);\n }\n return undefined;\n}\n\nexport function memberObject(node: unknown): unknown {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"MemberExpression\" ? current.object : undefined;\n}\n\nexport function calleePropertyName(node: unknown): string | undefined {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"CallExpression\" ? memberPropertyName(current.callee) : undefined;\n}\n\nexport function isIdentifierNamed(node: unknown, name: string): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Identifier\" && current.name === name;\n}\n\nexport function isNegativeOneLiteral(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"Literal\" && current.value === -1) {\n return true;\n }\n return (\n current?.type === \"UnaryExpression\" &&\n current.operator === \"-\" &&\n current.argument?.type === \"Literal\" &&\n current.argument.value === 1\n );\n}\n\nexport function isZeroLiteral(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Literal\" && current.value === 0;\n}\n\nexport function isLiteralString(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Literal\" && typeof current.value === \"string\";\n}\n\nexport function isRegExpLiteral(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Literal\" && current.regex !== undefined;\n}\n\nexport function regexFlags(node: unknown): string | undefined {\n const current = stripChainExpression(node as any) as any;\n return isRegExpLiteral(current) ? current.regex.flags : undefined;\n}\n\nexport function hasUnknownTypeAnnotation(node: unknown): boolean {\n const current = node as any;\n return (\n current?.typeAnnotation?.typeAnnotation?.type === \"TSUnknownKeyword\" ||\n current?.typeAnnotation?.type === \"TSUnknownKeyword\"\n );\n}\n\nexport function nearestFunctionAncestors(node: any, sourceCode: any): any[] {\n return sourceCode\n .getAncestors(node)\n .toReversed()\n .filter((ancestor: any) => ancestor.type?.includes(\"Function\"));\n}\n"],"mappings":";AAAA,SAAgB,qBAA2B,MAAkB;CAC3D,IAAI,UAAU;AACd,QAAO,SAAS,SAAS,kBACvB,WAAU,QAAQ;AAEpB,QAAO;;AAGT,SAAgB,mBAAmB,MAAmC;CACpE,MAAM,UAAU,qBAAqB,KAAY;AACjD,KAAI,CAAC,WAAW,QAAQ,SAAS,mBAC/B;AAEF,KAAI,CAAC,QAAQ,YAAY,QAAQ,UAAU,SAAS,aAClD,QAAO,QAAQ,SAAS;AAE1B,KAAI,QAAQ,YAAY,QAAQ,UAAU,SAAS,UACjD,QAAO,OAAO,QAAQ,SAAS,MAAM;;AAKzC,SAAgB,aAAa,MAAwB;CACnD,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,SAAS,SAAS,qBAAqB,QAAQ,SAAS,KAAA;;AAGjE,SAAgB,mBAAmB,MAAmC;CACpE,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,SAAS,SAAS,mBAAmB,mBAAmB,QAAQ,OAAO,GAAG,KAAA;;AAGnF,SAAgB,kBAAkB,MAAe,MAAuB;CACtE,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,SAAS,SAAS,gBAAgB,QAAQ,SAAS;;AAG5D,SAAgB,qBAAqB,MAAwB;CAC3D,MAAM,UAAU,qBAAqB,KAAY;AACjD,KAAI,SAAS,SAAS,aAAa,QAAQ,UAAU,GACnD,QAAO;AAET,QACE,SAAS,SAAS,qBAClB,QAAQ,aAAa,OACrB,QAAQ,UAAU,SAAS,aAC3B,QAAQ,SAAS,UAAU;;AAI/B,SAAgB,cAAc,MAAwB;CACpD,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,SAAS,SAAS,aAAa,QAAQ,UAAU;;AAG1D,SAAgB,gBAAgB,MAAwB;CACtD,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,SAAS,SAAS,aAAa,OAAO,QAAQ,UAAU;;AAGjE,SAAgB,gBAAgB,MAAwB;CACtD,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,SAAS,SAAS,aAAa,QAAQ,UAAU,KAAA;;AAG1D,SAAgB,WAAW,MAAmC;CAC5D,MAAM,UAAU,qBAAqB,KAAY;AACjD,QAAO,gBAAgB,QAAQ,GAAG,QAAQ,MAAM,QAAQ,KAAA;;AAG1D,SAAgB,yBAAyB,MAAwB;CAC/D,MAAM,UAAU;AAChB,QACE,SAAS,gBAAgB,gBAAgB,SAAS,sBAClD,SAAS,gBAAgB,SAAS;;AAItC,SAAgB,yBAAyB,MAAW,YAAwB;AAC1E,QAAO,WACJ,aAAa,KAAK,CAClB,YAAY,CACZ,QAAQ,aAAkB,SAAS,MAAM,SAAS,WAAW,CAAC"}
1
+ {"version":3,"file":"ast.js","names":[],"sources":["../../ts/rules/ast.ts"],"sourcesContent":["export function stripChainExpression<Node>(node: Node): Node {\n let current = node as any;\n while (current?.type === \"ChainExpression\") {\n current = current.expression;\n }\n return current as Node;\n}\n\nexport function memberPropertyName(node: unknown): string | undefined {\n const current = stripChainExpression(node as any) as any;\n if (!current || current.type !== \"MemberExpression\") {\n return undefined;\n }\n if (!current.computed && current.property?.type === \"Identifier\") {\n return current.property.name;\n }\n if (current.computed && current.property?.type === \"Literal\") {\n return String(current.property.value);\n }\n return undefined;\n}\n\nexport function memberObject(node: unknown): unknown {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"MemberExpression\" ? current.object : undefined;\n}\n\nexport function calleePropertyName(node: unknown): string | undefined {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"CallExpression\" ? memberPropertyName(current.callee) : undefined;\n}\n\nexport function isIdentifierNamed(node: unknown, name: string): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Identifier\" && current.name === name;\n}\n\nexport function isNegativeOneLiteral(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"Literal\" && current.value === -1) {\n return true;\n }\n return (\n current?.type === \"UnaryExpression\" &&\n current.operator === \"-\" &&\n current.argument?.type === \"Literal\" &&\n current.argument.value === 1\n );\n}\n\nexport function isZeroLiteral(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Literal\" && current.value === 0;\n}\n\nexport function isLiteralString(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Literal\" && typeof current.value === \"string\";\n}\n\nexport function isRegExpLiteral(node: unknown): boolean {\n const current = stripChainExpression(node as any) as any;\n return current?.type === \"Literal\" && current.regex !== undefined;\n}\n\nexport function regexFlags(node: unknown): string | undefined {\n const current = stripChainExpression(node as any) as any;\n return isRegExpLiteral(current) ? current.regex.flags : undefined;\n}\n\nexport function hasUnknownTypeAnnotation(node: unknown): boolean {\n const current = node as any;\n return (\n current?.typeAnnotation?.typeAnnotation?.type === \"TSUnknownKeyword\" ||\n current?.typeAnnotation?.type === \"TSUnknownKeyword\"\n );\n}\n\nexport function nearestFunctionAncestors(node: any, sourceCode: any): any[] {\n return sourceCode\n .getAncestors(node)\n .toReversed()\n .filter((ancestor: any) => ancestor.type?.includes(\"Function\"));\n}\n"],"mappings":";AAAA,SAAgB,qBAA2B,MAAkB;CAC3D,IAAI,UAAU;CACd,OAAO,SAAS,SAAS,mBACvB,UAAU,QAAQ;CAEpB,OAAO;;AAGT,SAAgB,mBAAmB,MAAmC;CACpE,MAAM,UAAU,qBAAqB,KAAY;CACjD,IAAI,CAAC,WAAW,QAAQ,SAAS,oBAC/B;CAEF,IAAI,CAAC,QAAQ,YAAY,QAAQ,UAAU,SAAS,cAClD,OAAO,QAAQ,SAAS;CAE1B,IAAI,QAAQ,YAAY,QAAQ,UAAU,SAAS,WACjD,OAAO,OAAO,QAAQ,SAAS,MAAM;;AAKzC,SAAgB,aAAa,MAAwB;CACnD,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,SAAS,SAAS,qBAAqB,QAAQ,SAAS,KAAA;;AAGjE,SAAgB,mBAAmB,MAAmC;CACpE,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,SAAS,SAAS,mBAAmB,mBAAmB,QAAQ,OAAO,GAAG,KAAA;;AAGnF,SAAgB,kBAAkB,MAAe,MAAuB;CACtE,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,SAAS,SAAS,gBAAgB,QAAQ,SAAS;;AAG5D,SAAgB,qBAAqB,MAAwB;CAC3D,MAAM,UAAU,qBAAqB,KAAY;CACjD,IAAI,SAAS,SAAS,aAAa,QAAQ,UAAU,IACnD,OAAO;CAET,OACE,SAAS,SAAS,qBAClB,QAAQ,aAAa,OACrB,QAAQ,UAAU,SAAS,aAC3B,QAAQ,SAAS,UAAU;;AAI/B,SAAgB,cAAc,MAAwB;CACpD,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,SAAS,SAAS,aAAa,QAAQ,UAAU;;AAG1D,SAAgB,gBAAgB,MAAwB;CACtD,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,SAAS,SAAS,aAAa,OAAO,QAAQ,UAAU;;AAGjE,SAAgB,gBAAgB,MAAwB;CACtD,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,SAAS,SAAS,aAAa,QAAQ,UAAU,KAAA;;AAG1D,SAAgB,WAAW,MAAmC;CAC5D,MAAM,UAAU,qBAAqB,KAAY;CACjD,OAAO,gBAAgB,QAAQ,GAAG,QAAQ,MAAM,QAAQ,KAAA;;AAG1D,SAAgB,yBAAyB,MAAwB;CAC/D,MAAM,UAAU;CAChB,OACE,SAAS,gBAAgB,gBAAgB,SAAS,sBAClD,SAAS,gBAAgB,SAAS;;AAItC,SAAgB,yBAAyB,MAAW,YAAwB;CAC1E,OAAO,WACJ,aAAa,KAAK,CAClB,YAAY,CACZ,QAAQ,aAAkB,SAAS,MAAM,SAAS,WAAW,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"native_bridge.js","names":[],"sources":["../../ts/rules/native_bridge.ts"],"sourcesContent":["import { nativeLintRuleMetas, runNativeLintRule } from \"@corsa-bind/napi\";\nimport type {\n NativeLintDiagnostic,\n NativeLintNode,\n NativeLintRange,\n NativeLintRuleMeta,\n} from \"@corsa-bind/napi\";\n\nimport { createNativeRule } from \"./rule_creator\";\nimport { propertyNamesOfNode, typeTextsAtNode } from \"./type_utils\";\nimport type { ContextWithParserOptions } from \"../types\";\n\ntype RangedNode = {\n readonly type: string;\n readonly range: readonly [number, number];\n};\n\nconst MAX_NATIVE_NODE_DEPTH = 4;\nconst nativeRuleMetasByName = new Map(nativeLintRuleMetas().map((meta) => [meta.name, meta]));\n\nexport function createRustNativeRule(ruleName: string) {\n const meta = nativeRuleMeta(ruleName);\n return createNativeRule(\n ruleName,\n {\n docs: {\n description: meta.docsDescription,\n },\n hasSuggestions: meta.hasSuggestions,\n messages: meta.messages,\n },\n (context) =>\n Object.fromEntries(\n meta.listeners.map((listener) => [\n listener,\n (node: RangedNode) => {\n reportNativeDiagnostics(\n context,\n node,\n runNativeLintRule(ruleName, toNativeNode(context, node, meta.requiresTypeTexts)),\n );\n },\n ]),\n ),\n );\n}\n\nexport function toNativeNode(\n context: ContextWithParserOptions,\n node: RangedNode,\n includeTypeTexts = true,\n maxDepth = MAX_NATIVE_NODE_DEPTH,\n): NativeLintNode {\n const fields: Record<string, unknown> = {};\n const children: Record<string, NativeLintNode> = {};\n const childLists: Record<string, NativeLintNode[]> = {};\n\n for (const [key, value] of Object.entries(node)) {\n if (isSkippedField(key)) {\n continue;\n }\n if (isNativeChildNode(value)) {\n if (maxDepth > 0) {\n children[key] = toNativeNode(context, value, includeTypeTexts, maxDepth - 1);\n }\n continue;\n }\n if (Array.isArray(value)) {\n if (maxDepth > 0 && value.every(isNativeChildNode)) {\n childLists[key] = value.map((child) =>\n toNativeNode(context, child, includeTypeTexts, maxDepth - 1),\n );\n } else if (value.every(isJsonPrimitive)) {\n fields[key] = value;\n }\n continue;\n }\n if (isPrimitiveRecord(value)) {\n fields[key] = value;\n continue;\n }\n if (isJsonPrimitive(value)) {\n fields[key] = value;\n }\n }\n\n const nativeNode: NativeLintNode = {\n kind: node.type,\n range: nativeRange(node.range),\n };\n if (includeTypeTexts) {\n nativeNode.typeTexts = typeTextsAtNode(context, node);\n nativeNode.propertyNames = propertyNamesOfNode(context, node);\n }\n if (Object.keys(fields).length > 0) {\n nativeNode.fields = fields;\n }\n if (Object.keys(children).length > 0) {\n nativeNode.children = children;\n }\n if (Object.keys(childLists).length > 0) {\n nativeNode.childLists = childLists;\n }\n return nativeNode;\n}\n\nexport function reportNativeDiagnostics(\n context: ContextWithParserOptions,\n node: RangedNode,\n diagnostics: readonly NativeLintDiagnostic[],\n): void {\n for (const diagnostic of diagnostics) {\n context.report({\n node: reportNodeForRange(node, diagnostic.range),\n messageId: diagnostic.messageId,\n ...(diagnostic.suggestions?.length\n ? {\n suggest: diagnostic.suggestions.map((suggestion) => ({\n messageId: suggestion.messageId,\n fix: (fixer: any) =>\n suggestion.fixes.map((fix) =>\n fixer.replaceTextRange(oxlintRange(fix.range), fix.replacementText),\n ),\n })),\n }\n : {}),\n } as never);\n }\n}\n\nfunction reportNodeForRange(root: RangedNode, range: NativeLintRange): RangedNode {\n return findNodeByRange(root, range) ?? root;\n}\n\nfunction findNodeByRange(\n value: unknown,\n range: NativeLintRange,\n seen = new Set<object>(),\n): RangedNode | undefined {\n if (typeof value !== \"object\" || value === null || seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (isNativeChildNode(value) && sameRange(value.range, range)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n const match = findNodeByRange(item, range, seen);\n if (match) {\n return match;\n }\n }\n return undefined;\n }\n\n for (const [key, child] of Object.entries(value)) {\n if (isSkippedField(key)) {\n continue;\n }\n const match = findNodeByRange(child, range, seen);\n if (match) {\n return match;\n }\n }\n return undefined;\n}\n\nfunction nativeRuleMeta(ruleName: string): NativeLintRuleMeta {\n const meta = nativeRuleMetasByName.get(ruleName);\n if (!meta) {\n throw new Error(`corsa-oxlint native Rust rule is not registered: ${ruleName}`);\n }\n return meta;\n}\n\nfunction nativeRange(range: readonly [number, number]): NativeLintRange {\n return { start: range[0], end: range[1] };\n}\n\nfunction oxlintRange(range: NativeLintRange): [number, number] {\n return [range.start, range.end];\n}\n\nfunction sameRange(range: readonly [number, number], expected: NativeLintRange): boolean {\n return range[0] === expected.start && range[1] === expected.end;\n}\n\nfunction isNativeChildNode(value: unknown): value is RangedNode {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\" &&\n isRange((value as { range?: unknown }).range)\n );\n}\n\nfunction isRange(value: unknown): value is readonly [number, number] {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n typeof value[0] === \"number\" &&\n typeof value[1] === \"number\"\n );\n}\n\nfunction isJsonPrimitive(value: unknown): value is string | number | boolean | null {\n return value === null || [\"boolean\", \"number\", \"string\"].includes(typeof value);\n}\n\nfunction isPrimitiveRecord(\n value: unknown,\n): value is Record<string, string | number | boolean | null> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every(isJsonPrimitive)\n );\n}\n\nfunction isSkippedField(key: string): boolean {\n return key === \"type\" || key === \"range\" || key === \"loc\" || key === \"parent\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"native_bridge.js","names":[],"sources":["../../ts/rules/native_bridge.ts"],"sourcesContent":["import { nativeLintRuleMetas, runNativeLintRule } from \"@corsa-bind/napi\";\nimport type {\n NativeLintDiagnostic,\n NativeLintNode,\n NativeLintRange,\n NativeLintRuleMeta,\n} from \"@corsa-bind/napi\";\n\nimport { createNativeRule } from \"./rule_creator\";\nimport { propertyNamesOfNode, typeTextsAtNode } from \"./type_utils\";\nimport type { ContextWithParserOptions } from \"../types\";\n\ntype RangedNode = {\n readonly type: string;\n readonly range: readonly [number, number];\n};\n\nconst MAX_NATIVE_NODE_DEPTH = 4;\nconst nativeRuleMetasByName = new Map(nativeLintRuleMetas().map((meta) => [meta.name, meta]));\n\nexport function createRustNativeRule(ruleName: string) {\n const meta = nativeRuleMeta(ruleName);\n return createNativeRule(\n ruleName,\n {\n docs: {\n description: meta.docsDescription,\n },\n hasSuggestions: meta.hasSuggestions,\n messages: meta.messages,\n },\n (context) =>\n Object.fromEntries(\n meta.listeners.map((listener) => [\n listener,\n (node: RangedNode) => {\n reportNativeDiagnostics(\n context,\n node,\n runNativeLintRule(ruleName, toNativeNode(context, node, meta.requiresTypeTexts)),\n );\n },\n ]),\n ),\n );\n}\n\nexport function toNativeNode(\n context: ContextWithParserOptions,\n node: RangedNode,\n includeTypeTexts = true,\n maxDepth = MAX_NATIVE_NODE_DEPTH,\n): NativeLintNode {\n const fields: Record<string, unknown> = {};\n const children: Record<string, NativeLintNode> = {};\n const childLists: Record<string, NativeLintNode[]> = {};\n\n for (const [key, value] of Object.entries(node)) {\n if (isSkippedField(key)) {\n continue;\n }\n if (isNativeChildNode(value)) {\n if (maxDepth > 0) {\n children[key] = toNativeNode(context, value, includeTypeTexts, maxDepth - 1);\n }\n continue;\n }\n if (Array.isArray(value)) {\n if (maxDepth > 0 && value.every(isNativeChildNode)) {\n childLists[key] = value.map((child) =>\n toNativeNode(context, child, includeTypeTexts, maxDepth - 1),\n );\n } else if (value.every(isJsonPrimitive)) {\n fields[key] = value;\n }\n continue;\n }\n if (isPrimitiveRecord(value)) {\n fields[key] = value;\n continue;\n }\n if (isJsonPrimitive(value)) {\n fields[key] = value;\n }\n }\n\n const nativeNode: NativeLintNode = {\n kind: node.type,\n range: nativeRange(node.range),\n };\n if (includeTypeTexts) {\n nativeNode.typeTexts = typeTextsAtNode(context, node);\n nativeNode.propertyNames = propertyNamesOfNode(context, node);\n }\n if (Object.keys(fields).length > 0) {\n nativeNode.fields = fields;\n }\n if (Object.keys(children).length > 0) {\n nativeNode.children = children;\n }\n if (Object.keys(childLists).length > 0) {\n nativeNode.childLists = childLists;\n }\n return nativeNode;\n}\n\nexport function reportNativeDiagnostics(\n context: ContextWithParserOptions,\n node: RangedNode,\n diagnostics: readonly NativeLintDiagnostic[],\n): void {\n for (const diagnostic of diagnostics) {\n context.report({\n node: reportNodeForRange(node, diagnostic.range),\n messageId: diagnostic.messageId,\n ...(diagnostic.suggestions?.length\n ? {\n suggest: diagnostic.suggestions.map((suggestion) => ({\n messageId: suggestion.messageId,\n fix: (fixer: any) =>\n suggestion.fixes.map((fix) =>\n fixer.replaceTextRange(oxlintRange(fix.range), fix.replacementText),\n ),\n })),\n }\n : {}),\n } as never);\n }\n}\n\nfunction reportNodeForRange(root: RangedNode, range: NativeLintRange): RangedNode {\n return findNodeByRange(root, range) ?? root;\n}\n\nfunction findNodeByRange(\n value: unknown,\n range: NativeLintRange,\n seen = new Set<object>(),\n): RangedNode | undefined {\n if (typeof value !== \"object\" || value === null || seen.has(value)) {\n return undefined;\n }\n seen.add(value);\n\n if (isNativeChildNode(value) && sameRange(value.range, range)) {\n return value;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n const match = findNodeByRange(item, range, seen);\n if (match) {\n return match;\n }\n }\n return undefined;\n }\n\n for (const [key, child] of Object.entries(value)) {\n if (isSkippedField(key)) {\n continue;\n }\n const match = findNodeByRange(child, range, seen);\n if (match) {\n return match;\n }\n }\n return undefined;\n}\n\nfunction nativeRuleMeta(ruleName: string): NativeLintRuleMeta {\n const meta = nativeRuleMetasByName.get(ruleName);\n if (!meta) {\n throw new Error(`corsa-oxlint native Rust rule is not registered: ${ruleName}`);\n }\n return meta;\n}\n\nfunction nativeRange(range: readonly [number, number]): NativeLintRange {\n return { start: range[0], end: range[1] };\n}\n\nfunction oxlintRange(range: NativeLintRange): [number, number] {\n return [range.start, range.end];\n}\n\nfunction sameRange(range: readonly [number, number], expected: NativeLintRange): boolean {\n return range[0] === expected.start && range[1] === expected.end;\n}\n\nfunction isNativeChildNode(value: unknown): value is RangedNode {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\" &&\n isRange((value as { range?: unknown }).range)\n );\n}\n\nfunction isRange(value: unknown): value is readonly [number, number] {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n typeof value[0] === \"number\" &&\n typeof value[1] === \"number\"\n );\n}\n\nfunction isJsonPrimitive(value: unknown): value is string | number | boolean | null {\n return value === null || [\"boolean\", \"number\", \"string\"].includes(typeof value);\n}\n\nfunction isPrimitiveRecord(\n value: unknown,\n): value is Record<string, string | number | boolean | null> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every(isJsonPrimitive)\n );\n}\n\nfunction isSkippedField(key: string): boolean {\n return key === \"type\" || key === \"range\" || key === \"loc\" || key === \"parent\";\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"no_base_to_string.js","names":[],"sources":["../../ts/rules/no_base_to_string.ts"],"sourcesContent":["import {\n calleePropertyName,\n isIdentifierNamed,\n isLiteralString,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport {\n classifyTypeText,\n isStringLikeNode,\n splitTopLevelTypeText,\n typeTextsAtNode,\n} from \"./type_utils\";\n\nconst knownSafeObjectTypes = new Set([\n \"Date\",\n \"Error\",\n \"EvalError\",\n \"RangeError\",\n \"ReferenceError\",\n \"RegExp\",\n \"SyntaxError\",\n \"TypeError\",\n \"URIError\",\n \"URL\",\n \"URLSearchParams\",\n]);\n\nexport const noBaseToStringRule = createNativeRule(\n \"no-base-to-string\",\n {\n docs: {\n description: \"Disallow stringifying values that fall back to Object.prototype.toString().\",\n },\n messages: {\n unexpected: \"This value is stringified through its base Object#toString() representation.\",\n },\n },\n (context) => ({\n BinaryExpression(node: any) {\n if (node.operator !== \"+\") {\n return;\n }\n if (isLiteralString(node.left) || isStringLikeNode(context, node.left)) {\n reportIfUnsafe(context, node.right);\n }\n if (isLiteralString(node.right) || isStringLikeNode(context, node.right)) {\n reportIfUnsafe(context, node.left);\n }\n },\n CallExpression(node: any) {\n const [firstArgument] = node.arguments;\n if (!firstArgument) {\n return;\n }\n if (isIdentifierNamed(node.callee, \"String\")) {\n reportIfUnsafe(context, firstArgument);\n return;\n }\n if (calleePropertyName(node) === \"toString\") {\n const callee = stripChainExpression(node.callee) as any;\n reportIfUnsafe(context, callee.object);\n }\n },\n TemplateLiteral(node: any) {\n for (const expression of node.expressions ?? []) {\n reportIfUnsafe(context, expression);\n }\n },\n }),\n);\n\nfunction reportIfUnsafe(context: any, node: any): void {\n if (!node || !isPossiblyBaseToString(context, node)) {\n return;\n }\n context.report({\n node,\n messageId: \"unexpected\",\n });\n}\n\nfunction isPossiblyBaseToString(context: any, node: any): boolean {\n const current = stripChainExpression(node) as any;\n if (\n current?.type === \"ArrayExpression\" ||\n current?.type === \"ObjectExpression\" ||\n current?.type === \"ArrowFunctionExpression\" ||\n current?.type === \"FunctionExpression\"\n ) {\n return true;\n }\n const typeTexts = typeTextsAtNode(context, node);\n if (typeTexts.length === 0) {\n return false;\n }\n return typeTexts.some((text) => splitTopLevelTypeText(text, \"|\").some(isUnsafeStringifiedText));\n}\n\nfunction isUnsafeStringifiedText(text: string): boolean {\n const current = text.trim();\n const kind = classifyTypeText(current);\n if (\n kind === \"string\" ||\n kind === \"number\" ||\n kind === \"bigint\" ||\n kind === \"boolean\" ||\n kind === \"nullish\" ||\n kind === \"regexp\"\n ) {\n return false;\n }\n if (current === \"symbol\") {\n return true;\n }\n if (knownSafeObjectTypes.has(current)) {\n return false;\n }\n if (\n current === \"object\" ||\n current === \"Object\" ||\n current.startsWith(\"{\") ||\n current.endsWith(\"[]\") ||\n current.startsWith(\"[\") ||\n current.startsWith(\"Array<\") ||\n current.startsWith(\"ReadonlyArray<\") ||\n current.startsWith(\"Map<\") ||\n current.startsWith(\"ReadonlyMap<\") ||\n current.startsWith(\"Set<\") ||\n current.startsWith(\"ReadonlySet<\") ||\n current.startsWith(\"Record<\") ||\n current.startsWith(\"WeakMap<\") ||\n current.startsWith(\"WeakSet<\") ||\n current.startsWith(\"Promise<\") ||\n current.includes(\"=>\")\n ) {\n return true;\n }\n return false;\n}\n"],"mappings":";;;;AAcA,MAAM,uBAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,qBAAqB,iBAChC,qBACA;CACE,MAAM,EACJ,aAAa,+EACd;CACD,UAAU,EACR,YAAY,gFACb;CACF,GACA,aAAa;CACZ,iBAAiB,MAAW;AAC1B,MAAI,KAAK,aAAa,IACpB;AAEF,MAAI,gBAAgB,KAAK,KAAK,IAAI,iBAAiB,SAAS,KAAK,KAAK,CACpE,gBAAe,SAAS,KAAK,MAAM;AAErC,MAAI,gBAAgB,KAAK,MAAM,IAAI,iBAAiB,SAAS,KAAK,MAAM,CACtE,gBAAe,SAAS,KAAK,KAAK;;CAGtC,eAAe,MAAW;EACxB,MAAM,CAAC,iBAAiB,KAAK;AAC7B,MAAI,CAAC,cACH;AAEF,MAAI,kBAAkB,KAAK,QAAQ,SAAS,EAAE;AAC5C,kBAAe,SAAS,cAAc;AACtC;;AAEF,MAAI,mBAAmB,KAAK,KAAK,WAE/B,gBAAe,SADA,qBAAqB,KAAK,OAAO,CACjB,OAAO;;CAG1C,gBAAgB,MAAW;AACzB,OAAK,MAAM,cAAc,KAAK,eAAe,EAAE,CAC7C,gBAAe,SAAS,WAAW;;CAGxC,EACF;AAED,SAAS,eAAe,SAAc,MAAiB;AACrD,KAAI,CAAC,QAAQ,CAAC,uBAAuB,SAAS,KAAK,CACjD;AAEF,SAAQ,OAAO;EACb;EACA,WAAW;EACZ,CAAC;;AAGJ,SAAS,uBAAuB,SAAc,MAAoB;CAChE,MAAM,UAAU,qBAAqB,KAAK;AAC1C,KACE,SAAS,SAAS,qBAClB,SAAS,SAAS,sBAClB,SAAS,SAAS,6BAClB,SAAS,SAAS,qBAElB,QAAO;CAET,MAAM,YAAY,gBAAgB,SAAS,KAAK;AAChD,KAAI,UAAU,WAAW,EACvB,QAAO;AAET,QAAO,UAAU,MAAM,SAAS,sBAAsB,MAAM,IAAI,CAAC,KAAK,wBAAwB,CAAC;;AAGjG,SAAS,wBAAwB,MAAuB;CACtD,MAAM,UAAU,KAAK,MAAM;CAC3B,MAAM,OAAO,iBAAiB,QAAQ;AACtC,KACE,SAAS,YACT,SAAS,YACT,SAAS,YACT,SAAS,aACT,SAAS,aACT,SAAS,SAET,QAAO;AAET,KAAI,YAAY,SACd,QAAO;AAET,KAAI,qBAAqB,IAAI,QAAQ,CACnC,QAAO;AAET,KACE,YAAY,YACZ,YAAY,YACZ,QAAQ,WAAW,IAAI,IACvB,QAAQ,SAAS,KAAK,IACtB,QAAQ,WAAW,IAAI,IACvB,QAAQ,WAAW,SAAS,IAC5B,QAAQ,WAAW,iBAAiB,IACpC,QAAQ,WAAW,OAAO,IAC1B,QAAQ,WAAW,eAAe,IAClC,QAAQ,WAAW,OAAO,IAC1B,QAAQ,WAAW,eAAe,IAClC,QAAQ,WAAW,UAAU,IAC7B,QAAQ,WAAW,WAAW,IAC9B,QAAQ,WAAW,WAAW,IAC9B,QAAQ,WAAW,WAAW,IAC9B,QAAQ,SAAS,KAAK,CAEtB,QAAO;AAET,QAAO"}
1
+ {"version":3,"file":"no_base_to_string.js","names":[],"sources":["../../ts/rules/no_base_to_string.ts"],"sourcesContent":["import {\n calleePropertyName,\n isIdentifierNamed,\n isLiteralString,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport {\n classifyTypeText,\n isStringLikeNode,\n splitTopLevelTypeText,\n typeTextsAtNode,\n} from \"./type_utils\";\n\nconst knownSafeObjectTypes = new Set([\n \"Date\",\n \"Error\",\n \"EvalError\",\n \"RangeError\",\n \"ReferenceError\",\n \"RegExp\",\n \"SyntaxError\",\n \"TypeError\",\n \"URIError\",\n \"URL\",\n \"URLSearchParams\",\n]);\n\nexport const noBaseToStringRule = createNativeRule(\n \"no-base-to-string\",\n {\n docs: {\n description: \"Disallow stringifying values that fall back to Object.prototype.toString().\",\n },\n messages: {\n unexpected: \"This value is stringified through its base Object#toString() representation.\",\n },\n },\n (context) => ({\n BinaryExpression(node: any) {\n if (node.operator !== \"+\") {\n return;\n }\n if (isLiteralString(node.left) || isStringLikeNode(context, node.left)) {\n reportIfUnsafe(context, node.right);\n }\n if (isLiteralString(node.right) || isStringLikeNode(context, node.right)) {\n reportIfUnsafe(context, node.left);\n }\n },\n CallExpression(node: any) {\n const [firstArgument] = node.arguments;\n if (!firstArgument) {\n return;\n }\n if (isIdentifierNamed(node.callee, \"String\")) {\n reportIfUnsafe(context, firstArgument);\n return;\n }\n if (calleePropertyName(node) === \"toString\") {\n const callee = stripChainExpression(node.callee) as any;\n reportIfUnsafe(context, callee.object);\n }\n },\n TemplateLiteral(node: any) {\n for (const expression of node.expressions ?? []) {\n reportIfUnsafe(context, expression);\n }\n },\n }),\n);\n\nfunction reportIfUnsafe(context: any, node: any): void {\n if (!node || !isPossiblyBaseToString(context, node)) {\n return;\n }\n context.report({\n node,\n messageId: \"unexpected\",\n });\n}\n\nfunction isPossiblyBaseToString(context: any, node: any): boolean {\n const current = stripChainExpression(node) as any;\n if (\n current?.type === \"ArrayExpression\" ||\n current?.type === \"ObjectExpression\" ||\n current?.type === \"ArrowFunctionExpression\" ||\n current?.type === \"FunctionExpression\"\n ) {\n return true;\n }\n const typeTexts = typeTextsAtNode(context, node);\n if (typeTexts.length === 0) {\n return false;\n }\n return typeTexts.some((text) => splitTopLevelTypeText(text, \"|\").some(isUnsafeStringifiedText));\n}\n\nfunction isUnsafeStringifiedText(text: string): boolean {\n const current = text.trim();\n const kind = classifyTypeText(current);\n if (\n kind === \"string\" ||\n kind === \"number\" ||\n kind === \"bigint\" ||\n kind === \"boolean\" ||\n kind === \"nullish\" ||\n kind === \"regexp\"\n ) {\n return false;\n }\n if (current === \"symbol\") {\n return true;\n }\n if (knownSafeObjectTypes.has(current)) {\n return false;\n }\n if (\n current === \"object\" ||\n current === \"Object\" ||\n current.startsWith(\"{\") ||\n current.endsWith(\"[]\") ||\n current.startsWith(\"[\") ||\n current.startsWith(\"Array<\") ||\n current.startsWith(\"ReadonlyArray<\") ||\n current.startsWith(\"Map<\") ||\n current.startsWith(\"ReadonlyMap<\") ||\n current.startsWith(\"Set<\") ||\n current.startsWith(\"ReadonlySet<\") ||\n current.startsWith(\"Record<\") ||\n current.startsWith(\"WeakMap<\") ||\n current.startsWith(\"WeakSet<\") ||\n current.startsWith(\"Promise<\") ||\n current.includes(\"=>\")\n ) {\n return true;\n }\n return false;\n}\n"],"mappings":";;;;AAcA,MAAM,uBAAuB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAa,qBAAqB,iBAChC,qBACA;CACE,MAAM,EACJ,aAAa,+EACd;CACD,UAAU,EACR,YAAY,gFACb;CACF,GACA,aAAa;CACZ,iBAAiB,MAAW;EAC1B,IAAI,KAAK,aAAa,KACpB;EAEF,IAAI,gBAAgB,KAAK,KAAK,IAAI,iBAAiB,SAAS,KAAK,KAAK,EACpE,eAAe,SAAS,KAAK,MAAM;EAErC,IAAI,gBAAgB,KAAK,MAAM,IAAI,iBAAiB,SAAS,KAAK,MAAM,EACtE,eAAe,SAAS,KAAK,KAAK;;CAGtC,eAAe,MAAW;EACxB,MAAM,CAAC,iBAAiB,KAAK;EAC7B,IAAI,CAAC,eACH;EAEF,IAAI,kBAAkB,KAAK,QAAQ,SAAS,EAAE;GAC5C,eAAe,SAAS,cAAc;GACtC;;EAEF,IAAI,mBAAmB,KAAK,KAAK,YAE/B,eAAe,SADA,qBAAqB,KAAK,OACX,CAAC,OAAO;;CAG1C,gBAAgB,MAAW;EACzB,KAAK,MAAM,cAAc,KAAK,eAAe,EAAE,EAC7C,eAAe,SAAS,WAAW;;CAGxC,EACF;AAED,SAAS,eAAe,SAAc,MAAiB;CACrD,IAAI,CAAC,QAAQ,CAAC,uBAAuB,SAAS,KAAK,EACjD;CAEF,QAAQ,OAAO;EACb;EACA,WAAW;EACZ,CAAC;;AAGJ,SAAS,uBAAuB,SAAc,MAAoB;CAChE,MAAM,UAAU,qBAAqB,KAAK;CAC1C,IACE,SAAS,SAAS,qBAClB,SAAS,SAAS,sBAClB,SAAS,SAAS,6BAClB,SAAS,SAAS,sBAElB,OAAO;CAET,MAAM,YAAY,gBAAgB,SAAS,KAAK;CAChD,IAAI,UAAU,WAAW,GACvB,OAAO;CAET,OAAO,UAAU,MAAM,SAAS,sBAAsB,MAAM,IAAI,CAAC,KAAK,wBAAwB,CAAC;;AAGjG,SAAS,wBAAwB,MAAuB;CACtD,MAAM,UAAU,KAAK,MAAM;CAC3B,MAAM,OAAO,iBAAiB,QAAQ;CACtC,IACE,SAAS,YACT,SAAS,YACT,SAAS,YACT,SAAS,aACT,SAAS,aACT,SAAS,UAET,OAAO;CAET,IAAI,YAAY,UACd,OAAO;CAET,IAAI,qBAAqB,IAAI,QAAQ,EACnC,OAAO;CAET,IACE,YAAY,YACZ,YAAY,YACZ,QAAQ,WAAW,IAAI,IACvB,QAAQ,SAAS,KAAK,IACtB,QAAQ,WAAW,IAAI,IACvB,QAAQ,WAAW,SAAS,IAC5B,QAAQ,WAAW,iBAAiB,IACpC,QAAQ,WAAW,OAAO,IAC1B,QAAQ,WAAW,eAAe,IAClC,QAAQ,WAAW,OAAO,IAC1B,QAAQ,WAAW,eAAe,IAClC,QAAQ,WAAW,UAAU,IAC7B,QAAQ,WAAW,WAAW,IAC9B,QAAQ,WAAW,WAAW,IAC9B,QAAQ,WAAW,WAAW,IAC9B,QAAQ,SAAS,KAAK,EAEtB,OAAO;CAET,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"no_floating_promises.js","names":[],"sources":["../../ts/rules/no_floating_promises.ts"],"sourcesContent":["import {\n calleePropertyName,\n memberObject,\n nearestFunctionAncestors,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isPromiseLikeNode } from \"./type_utils\";\n\nexport const noFloatingPromisesRule = createNativeRule(\n \"no-floating-promises\",\n {\n docs: {\n description: \"Require promises to be awaited or otherwise handled.\",\n },\n hasSuggestions: true,\n messages: {\n unexpected: \"Promises must be awaited, returned, or explicitly ignored with void.\",\n },\n },\n (context) => ({\n ExpressionStatement(node: any) {\n const expression = stripChainExpression(node.expression);\n if (expression?.type === \"UnaryExpression\" && expression.operator === \"void\") {\n return;\n }\n if (!isPromiseLikeNode(context, expression) || isHandled(expression)) {\n return;\n }\n context.report({\n node,\n messageId: \"unexpected\",\n suggest: buildSuggestions(context, node),\n });\n },\n }),\n);\n\nfunction isHandled(node: any): boolean {\n const current = stripChainExpression(node);\n const propertyName = calleePropertyName(current);\n if (!propertyName) {\n return false;\n }\n if (propertyName === \"catch\") {\n return current.arguments.length > 0;\n }\n if (propertyName === \"then\") {\n return current.arguments.length > 1;\n }\n if (propertyName === \"finally\") {\n return isHandled(memberObject(current.callee));\n }\n return false;\n}\n\nfunction buildSuggestions(context: any, node: any) {\n const suggestions = [\n {\n desc: \"Prefix the expression with void.\",\n fix: (fixer: any) => fixer.insertTextBefore(node.expression, \"void \"),\n },\n ];\n const nearestFunction = nearestFunctionAncestors(node, context.sourceCode)[0];\n if (nearestFunction?.async) {\n suggestions.push({\n desc: \"Await the promise.\",\n fix: (fixer: any) => fixer.insertTextBefore(node.expression, \"await \"),\n });\n }\n return suggestions;\n}\n"],"mappings":";;;;AASA,MAAa,yBAAyB,iBACpC,wBACA;CACE,MAAM,EACJ,aAAa,wDACd;CACD,gBAAgB;CAChB,UAAU,EACR,YAAY,wEACb;CACF,GACA,aAAa,EACZ,oBAAoB,MAAW;CAC7B,MAAM,aAAa,qBAAqB,KAAK,WAAW;AACxD,KAAI,YAAY,SAAS,qBAAqB,WAAW,aAAa,OACpE;AAEF,KAAI,CAAC,kBAAkB,SAAS,WAAW,IAAI,UAAU,WAAW,CAClE;AAEF,SAAQ,OAAO;EACb;EACA,WAAW;EACX,SAAS,iBAAiB,SAAS,KAAK;EACzC,CAAC;GAEL,EACF;AAED,SAAS,UAAU,MAAoB;CACrC,MAAM,UAAU,qBAAqB,KAAK;CAC1C,MAAM,eAAe,mBAAmB,QAAQ;AAChD,KAAI,CAAC,aACH,QAAO;AAET,KAAI,iBAAiB,QACnB,QAAO,QAAQ,UAAU,SAAS;AAEpC,KAAI,iBAAiB,OACnB,QAAO,QAAQ,UAAU,SAAS;AAEpC,KAAI,iBAAiB,UACnB,QAAO,UAAU,aAAa,QAAQ,OAAO,CAAC;AAEhD,QAAO;;AAGT,SAAS,iBAAiB,SAAc,MAAW;CACjD,MAAM,cAAc,CAClB;EACE,MAAM;EACN,MAAM,UAAe,MAAM,iBAAiB,KAAK,YAAY,QAAQ;EACtE,CACF;AAED,KADwB,yBAAyB,MAAM,QAAQ,WAAW,CAAC,IACtD,MACnB,aAAY,KAAK;EACf,MAAM;EACN,MAAM,UAAe,MAAM,iBAAiB,KAAK,YAAY,SAAS;EACvE,CAAC;AAEJ,QAAO"}
1
+ {"version":3,"file":"no_floating_promises.js","names":[],"sources":["../../ts/rules/no_floating_promises.ts"],"sourcesContent":["import {\n calleePropertyName,\n memberObject,\n nearestFunctionAncestors,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isPromiseLikeNode } from \"./type_utils\";\n\nexport const noFloatingPromisesRule = createNativeRule(\n \"no-floating-promises\",\n {\n docs: {\n description: \"Require promises to be awaited or otherwise handled.\",\n },\n hasSuggestions: true,\n messages: {\n unexpected: \"Promises must be awaited, returned, or explicitly ignored with void.\",\n },\n },\n (context) => ({\n ExpressionStatement(node: any) {\n const expression = stripChainExpression(node.expression);\n if (expression?.type === \"UnaryExpression\" && expression.operator === \"void\") {\n return;\n }\n if (!isPromiseLikeNode(context, expression) || isHandled(expression)) {\n return;\n }\n context.report({\n node,\n messageId: \"unexpected\",\n suggest: buildSuggestions(context, node),\n });\n },\n }),\n);\n\nfunction isHandled(node: any): boolean {\n const current = stripChainExpression(node);\n const propertyName = calleePropertyName(current);\n if (!propertyName) {\n return false;\n }\n if (propertyName === \"catch\") {\n return current.arguments.length > 0;\n }\n if (propertyName === \"then\") {\n return current.arguments.length > 1;\n }\n if (propertyName === \"finally\") {\n return isHandled(memberObject(current.callee));\n }\n return false;\n}\n\nfunction buildSuggestions(context: any, node: any) {\n const suggestions = [\n {\n desc: \"Prefix the expression with void.\",\n fix: (fixer: any) => fixer.insertTextBefore(node.expression, \"void \"),\n },\n ];\n const nearestFunction = nearestFunctionAncestors(node, context.sourceCode)[0];\n if (nearestFunction?.async) {\n suggestions.push({\n desc: \"Await the promise.\",\n fix: (fixer: any) => fixer.insertTextBefore(node.expression, \"await \"),\n });\n }\n return suggestions;\n}\n"],"mappings":";;;;AASA,MAAa,yBAAyB,iBACpC,wBACA;CACE,MAAM,EACJ,aAAa,wDACd;CACD,gBAAgB;CAChB,UAAU,EACR,YAAY,wEACb;CACF,GACA,aAAa,EACZ,oBAAoB,MAAW;CAC7B,MAAM,aAAa,qBAAqB,KAAK,WAAW;CACxD,IAAI,YAAY,SAAS,qBAAqB,WAAW,aAAa,QACpE;CAEF,IAAI,CAAC,kBAAkB,SAAS,WAAW,IAAI,UAAU,WAAW,EAClE;CAEF,QAAQ,OAAO;EACb;EACA,WAAW;EACX,SAAS,iBAAiB,SAAS,KAAK;EACzC,CAAC;GAEL,EACF;AAED,SAAS,UAAU,MAAoB;CACrC,MAAM,UAAU,qBAAqB,KAAK;CAC1C,MAAM,eAAe,mBAAmB,QAAQ;CAChD,IAAI,CAAC,cACH,OAAO;CAET,IAAI,iBAAiB,SACnB,OAAO,QAAQ,UAAU,SAAS;CAEpC,IAAI,iBAAiB,QACnB,OAAO,QAAQ,UAAU,SAAS;CAEpC,IAAI,iBAAiB,WACnB,OAAO,UAAU,aAAa,QAAQ,OAAO,CAAC;CAEhD,OAAO;;AAGT,SAAS,iBAAiB,SAAc,MAAW;CACjD,MAAM,cAAc,CAClB;EACE,MAAM;EACN,MAAM,UAAe,MAAM,iBAAiB,KAAK,YAAY,QAAQ;EACtE,CACF;CAED,IADwB,yBAAyB,MAAM,QAAQ,WAAW,CAAC,IACtD,OACnB,YAAY,KAAK;EACf,MAAM;EACN,MAAM,UAAe,MAAM,iBAAiB,KAAK,YAAY,SAAS;EACvE,CAAC;CAEJ,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"no_unsafe_assignment.js","names":[],"sources":["../../ts/rules/no_unsafe_assignment.ts"],"sourcesContent":["import { isUnsafeAssignment } from \"@corsa-bind/napi\";\n\nimport { createNativeRule } from \"./rule_creator\";\nimport { typeTextsAtNode } from \"./type_utils\";\n\nexport const noUnsafeAssignmentRule = createNativeRule(\n \"no-unsafe-assignment\",\n {\n docs: {\n description: \"Disallow assigning any-typed values to more specific targets.\",\n },\n messages: {\n unsafe: \"Unsafe assignment of an any-typed value.\",\n },\n },\n (context) => ({\n AssignmentExpression(node: any) {\n if (node.operator !== \"=\") {\n return;\n }\n reportIfUnsafe(context, node.right, typeTextsAtNode(context, node.left), node);\n },\n PropertyDefinition(node: any) {\n if (!node.value) {\n return;\n }\n reportIfUnsafe(context, node.value, targetTypeTextsForNode(context, node), node);\n },\n VariableDeclarator(node: any) {\n if (!node.init) {\n return;\n }\n reportIfUnsafe(context, node.init, targetTypeTextsForNode(context, node.id), node);\n },\n }),\n);\n\nfunction reportIfUnsafe(\n context: any,\n sourceNode: any,\n targetTypeTexts: readonly string[],\n reportNode: any,\n): void {\n const sourceTypeTexts = typeTextsAtNode(context, sourceNode);\n if (\n !isUnsafeAssignment({\n sourceTypeTexts,\n targetTypeTexts,\n })\n ) {\n return;\n }\n context.report({\n node: reportNode,\n messageId: \"unsafe\",\n });\n}\n\nfunction targetTypeTextsForNode(context: any, node: any): readonly string[] {\n const annotation = node?.typeAnnotation?.typeAnnotation ?? node?.typeAnnotation;\n if (!annotation) {\n return [];\n }\n const text = context.sourceCode.getText(annotation);\n return text ? [text] : [];\n}\n"],"mappings":";;;;AAKA,MAAa,yBAAyB,iBACpC,wBACA;CACE,MAAM,EACJ,aAAa,iEACd;CACD,UAAU,EACR,QAAQ,4CACT;CACF,GACA,aAAa;CACZ,qBAAqB,MAAW;AAC9B,MAAI,KAAK,aAAa,IACpB;AAEF,iBAAe,SAAS,KAAK,OAAO,gBAAgB,SAAS,KAAK,KAAK,EAAE,KAAK;;CAEhF,mBAAmB,MAAW;AAC5B,MAAI,CAAC,KAAK,MACR;AAEF,iBAAe,SAAS,KAAK,OAAO,uBAAuB,SAAS,KAAK,EAAE,KAAK;;CAElF,mBAAmB,MAAW;AAC5B,MAAI,CAAC,KAAK,KACR;AAEF,iBAAe,SAAS,KAAK,MAAM,uBAAuB,SAAS,KAAK,GAAG,EAAE,KAAK;;CAErF,EACF;AAED,SAAS,eACP,SACA,YACA,iBACA,YACM;AAEN,KACE,CAAC,mBAAmB;EAClB,iBAHoB,gBAAgB,SAAS,WAAW;EAIxD;EACD,CAAC,CAEF;AAEF,SAAQ,OAAO;EACb,MAAM;EACN,WAAW;EACZ,CAAC;;AAGJ,SAAS,uBAAuB,SAAc,MAA8B;CAC1E,MAAM,aAAa,MAAM,gBAAgB,kBAAkB,MAAM;AACjE,KAAI,CAAC,WACH,QAAO,EAAE;CAEX,MAAM,OAAO,QAAQ,WAAW,QAAQ,WAAW;AACnD,QAAO,OAAO,CAAC,KAAK,GAAG,EAAE"}
1
+ {"version":3,"file":"no_unsafe_assignment.js","names":[],"sources":["../../ts/rules/no_unsafe_assignment.ts"],"sourcesContent":["import { isUnsafeAssignment } from \"@corsa-bind/napi\";\n\nimport { createNativeRule } from \"./rule_creator\";\nimport { typeTextsAtNode } from \"./type_utils\";\n\nexport const noUnsafeAssignmentRule = createNativeRule(\n \"no-unsafe-assignment\",\n {\n docs: {\n description: \"Disallow assigning any-typed values to more specific targets.\",\n },\n messages: {\n unsafe: \"Unsafe assignment of an any-typed value.\",\n },\n },\n (context) => ({\n AssignmentExpression(node: any) {\n if (node.operator !== \"=\") {\n return;\n }\n reportIfUnsafe(context, node.right, typeTextsAtNode(context, node.left), node);\n },\n PropertyDefinition(node: any) {\n if (!node.value) {\n return;\n }\n reportIfUnsafe(context, node.value, targetTypeTextsForNode(context, node), node);\n },\n VariableDeclarator(node: any) {\n if (!node.init) {\n return;\n }\n reportIfUnsafe(context, node.init, targetTypeTextsForNode(context, node.id), node);\n },\n }),\n);\n\nfunction reportIfUnsafe(\n context: any,\n sourceNode: any,\n targetTypeTexts: readonly string[],\n reportNode: any,\n): void {\n const sourceTypeTexts = typeTextsAtNode(context, sourceNode);\n if (\n !isUnsafeAssignment({\n sourceTypeTexts,\n targetTypeTexts,\n })\n ) {\n return;\n }\n context.report({\n node: reportNode,\n messageId: \"unsafe\",\n });\n}\n\nfunction targetTypeTextsForNode(context: any, node: any): readonly string[] {\n const annotation = node?.typeAnnotation?.typeAnnotation ?? node?.typeAnnotation;\n if (!annotation) {\n return [];\n }\n const text = context.sourceCode.getText(annotation);\n return text ? [text] : [];\n}\n"],"mappings":";;;;AAKA,MAAa,yBAAyB,iBACpC,wBACA;CACE,MAAM,EACJ,aAAa,iEACd;CACD,UAAU,EACR,QAAQ,4CACT;CACF,GACA,aAAa;CACZ,qBAAqB,MAAW;EAC9B,IAAI,KAAK,aAAa,KACpB;EAEF,eAAe,SAAS,KAAK,OAAO,gBAAgB,SAAS,KAAK,KAAK,EAAE,KAAK;;CAEhF,mBAAmB,MAAW;EAC5B,IAAI,CAAC,KAAK,OACR;EAEF,eAAe,SAAS,KAAK,OAAO,uBAAuB,SAAS,KAAK,EAAE,KAAK;;CAElF,mBAAmB,MAAW;EAC5B,IAAI,CAAC,KAAK,MACR;EAEF,eAAe,SAAS,KAAK,MAAM,uBAAuB,SAAS,KAAK,GAAG,EAAE,KAAK;;CAErF,EACF;AAED,SAAS,eACP,SACA,YACA,iBACA,YACM;CAEN,IACE,CAAC,mBAAmB;EAClB,iBAHoB,gBAAgB,SAAS,WAG9B;EACf;EACD,CAAC,EAEF;CAEF,QAAQ,OAAO;EACb,MAAM;EACN,WAAW;EACZ,CAAC;;AAGJ,SAAS,uBAAuB,SAAc,MAA8B;CAC1E,MAAM,aAAa,MAAM,gBAAgB,kBAAkB,MAAM;CACjE,IAAI,CAAC,YACH,OAAO,EAAE;CAEX,MAAM,OAAO,QAAQ,WAAW,QAAQ,WAAW;CACnD,OAAO,OAAO,CAAC,KAAK,GAAG,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"no_unsafe_return.js","names":[],"sources":["../../ts/rules/no_unsafe_return.ts"],"sourcesContent":["import { isUnsafeReturn } from \"@corsa-bind/napi\";\n\nimport { nearestFunctionAncestors } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { checkerFor, typeAtNode, typeTextsAtNode } from \"./type_utils\";\n\nconst callSignatureKind = 0;\n\nexport const noUnsafeReturnRule = createNativeRule(\n \"no-unsafe-return\",\n {\n docs: {\n description: \"Disallow returning any-typed values from functions.\",\n },\n messages: {\n unsafe: \"Unsafe return of an any-typed value.\",\n },\n },\n (context) => ({\n ArrowFunctionExpression(node: any) {\n if (node.body?.type === \"BlockStatement\") {\n return;\n }\n reportIfUnsafeReturn(context, node.body, node);\n },\n ReturnStatement(node: any) {\n if (!node.argument) {\n return;\n }\n const [owner] = nearestFunctionAncestors(node, context.sourceCode);\n if (!owner) {\n return;\n }\n reportIfUnsafeReturn(context, node.argument, owner);\n },\n }),\n);\n\nfunction reportIfUnsafeReturn(context: any, expression: any, owner: any): void {\n const sourceTypeTexts = typeTextsAtNode(context, expression);\n const targetTypeTexts = returnTypeTextsOfFunction(context, owner);\n if (\n !isUnsafeReturn({\n sourceTypeTexts,\n targetTypeTexts,\n })\n ) {\n return;\n }\n context.report({\n node: expression,\n messageId: \"unsafe\",\n });\n}\n\nfunction returnTypeTextsOfFunction(context: any, node: any): readonly string[] {\n const explicitAnnotation = node.returnType?.typeAnnotation ?? node.returnType;\n if (explicitAnnotation) {\n const text = context.sourceCode.getText(explicitAnnotation);\n if (text) {\n return [text];\n }\n }\n\n const checker = checkerFor(context);\n const type = typeAtNode(context, node);\n if (!type) {\n return [];\n }\n\n const texts = new Set<string>();\n for (const signature of checker.getSignaturesOfType(type, callSignatureKind)) {\n const returnType = checker.getReturnTypeOfSignature(signature);\n if (!returnType) {\n continue;\n }\n for (const text of [...(returnType.texts ?? []), checker.typeToString(returnType)]) {\n if (text) {\n texts.add(text);\n }\n }\n }\n\n const resolved = [...texts];\n return resolved.every(isPermissiveTypeText) ? [] : resolved;\n}\n\nfunction isPermissiveTypeText(text: string): boolean {\n return text === \"any\" || text === \"unknown\" || text === \"never\";\n}\n"],"mappings":";;;;;AAMA,MAAM,oBAAoB;AAE1B,MAAa,qBAAqB,iBAChC,oBACA;CACE,MAAM,EACJ,aAAa,uDACd;CACD,UAAU,EACR,QAAQ,wCACT;CACF,GACA,aAAa;CACZ,wBAAwB,MAAW;AACjC,MAAI,KAAK,MAAM,SAAS,iBACtB;AAEF,uBAAqB,SAAS,KAAK,MAAM,KAAK;;CAEhD,gBAAgB,MAAW;AACzB,MAAI,CAAC,KAAK,SACR;EAEF,MAAM,CAAC,SAAS,yBAAyB,MAAM,QAAQ,WAAW;AAClE,MAAI,CAAC,MACH;AAEF,uBAAqB,SAAS,KAAK,UAAU,MAAM;;CAEtD,EACF;AAED,SAAS,qBAAqB,SAAc,YAAiB,OAAkB;AAG7E,KACE,CAAC,eAAe;EACd,iBAJoB,gBAAgB,SAAS,WAAW;EAKxD,iBAJoB,0BAA0B,SAAS,MAAM;EAK9D,CAAC,CAEF;AAEF,SAAQ,OAAO;EACb,MAAM;EACN,WAAW;EACZ,CAAC;;AAGJ,SAAS,0BAA0B,SAAc,MAA8B;CAC7E,MAAM,qBAAqB,KAAK,YAAY,kBAAkB,KAAK;AACnE,KAAI,oBAAoB;EACtB,MAAM,OAAO,QAAQ,WAAW,QAAQ,mBAAmB;AAC3D,MAAI,KACF,QAAO,CAAC,KAAK;;CAIjB,MAAM,UAAU,WAAW,QAAQ;CACnC,MAAM,OAAO,WAAW,SAAS,KAAK;AACtC,KAAI,CAAC,KACH,QAAO,EAAE;CAGX,MAAM,wBAAQ,IAAI,KAAa;AAC/B,MAAK,MAAM,aAAa,QAAQ,oBAAoB,MAAM,kBAAkB,EAAE;EAC5E,MAAM,aAAa,QAAQ,yBAAyB,UAAU;AAC9D,MAAI,CAAC,WACH;AAEF,OAAK,MAAM,QAAQ,CAAC,GAAI,WAAW,SAAS,EAAE,EAAG,QAAQ,aAAa,WAAW,CAAC,CAChF,KAAI,KACF,OAAM,IAAI,KAAK;;CAKrB,MAAM,WAAW,CAAC,GAAG,MAAM;AAC3B,QAAO,SAAS,MAAM,qBAAqB,GAAG,EAAE,GAAG;;AAGrD,SAAS,qBAAqB,MAAuB;AACnD,QAAO,SAAS,SAAS,SAAS,aAAa,SAAS"}
1
+ {"version":3,"file":"no_unsafe_return.js","names":[],"sources":["../../ts/rules/no_unsafe_return.ts"],"sourcesContent":["import { isUnsafeReturn } from \"@corsa-bind/napi\";\n\nimport { nearestFunctionAncestors } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { checkerFor, typeAtNode, typeTextsAtNode } from \"./type_utils\";\n\nconst callSignatureKind = 0;\n\nexport const noUnsafeReturnRule = createNativeRule(\n \"no-unsafe-return\",\n {\n docs: {\n description: \"Disallow returning any-typed values from functions.\",\n },\n messages: {\n unsafe: \"Unsafe return of an any-typed value.\",\n },\n },\n (context) => ({\n ArrowFunctionExpression(node: any) {\n if (node.body?.type === \"BlockStatement\") {\n return;\n }\n reportIfUnsafeReturn(context, node.body, node);\n },\n ReturnStatement(node: any) {\n if (!node.argument) {\n return;\n }\n const [owner] = nearestFunctionAncestors(node, context.sourceCode);\n if (!owner) {\n return;\n }\n reportIfUnsafeReturn(context, node.argument, owner);\n },\n }),\n);\n\nfunction reportIfUnsafeReturn(context: any, expression: any, owner: any): void {\n const sourceTypeTexts = typeTextsAtNode(context, expression);\n const targetTypeTexts = returnTypeTextsOfFunction(context, owner);\n if (\n !isUnsafeReturn({\n sourceTypeTexts,\n targetTypeTexts,\n })\n ) {\n return;\n }\n context.report({\n node: expression,\n messageId: \"unsafe\",\n });\n}\n\nfunction returnTypeTextsOfFunction(context: any, node: any): readonly string[] {\n const explicitAnnotation = node.returnType?.typeAnnotation ?? node.returnType;\n if (explicitAnnotation) {\n const text = context.sourceCode.getText(explicitAnnotation);\n if (text) {\n return [text];\n }\n }\n\n const checker = checkerFor(context);\n const type = typeAtNode(context, node);\n if (!type) {\n return [];\n }\n\n const texts = new Set<string>();\n for (const signature of checker.getSignaturesOfType(type, callSignatureKind)) {\n const returnType = checker.getReturnTypeOfSignature(signature);\n if (!returnType) {\n continue;\n }\n for (const text of [...(returnType.texts ?? []), checker.typeToString(returnType)]) {\n if (text) {\n texts.add(text);\n }\n }\n }\n\n const resolved = [...texts];\n return resolved.every(isPermissiveTypeText) ? [] : resolved;\n}\n\nfunction isPermissiveTypeText(text: string): boolean {\n return text === \"any\" || text === \"unknown\" || text === \"never\";\n}\n"],"mappings":";;;;;AAMA,MAAM,oBAAoB;AAE1B,MAAa,qBAAqB,iBAChC,oBACA;CACE,MAAM,EACJ,aAAa,uDACd;CACD,UAAU,EACR,QAAQ,wCACT;CACF,GACA,aAAa;CACZ,wBAAwB,MAAW;EACjC,IAAI,KAAK,MAAM,SAAS,kBACtB;EAEF,qBAAqB,SAAS,KAAK,MAAM,KAAK;;CAEhD,gBAAgB,MAAW;EACzB,IAAI,CAAC,KAAK,UACR;EAEF,MAAM,CAAC,SAAS,yBAAyB,MAAM,QAAQ,WAAW;EAClE,IAAI,CAAC,OACH;EAEF,qBAAqB,SAAS,KAAK,UAAU,MAAM;;CAEtD,EACF;AAED,SAAS,qBAAqB,SAAc,YAAiB,OAAkB;CAG7E,IACE,CAAC,eAAe;EACd,iBAJoB,gBAAgB,SAAS,WAI9B;EACf,iBAJoB,0BAA0B,SAAS,MAIxC;EAChB,CAAC,EAEF;CAEF,QAAQ,OAAO;EACb,MAAM;EACN,WAAW;EACZ,CAAC;;AAGJ,SAAS,0BAA0B,SAAc,MAA8B;CAC7E,MAAM,qBAAqB,KAAK,YAAY,kBAAkB,KAAK;CACnE,IAAI,oBAAoB;EACtB,MAAM,OAAO,QAAQ,WAAW,QAAQ,mBAAmB;EAC3D,IAAI,MACF,OAAO,CAAC,KAAK;;CAIjB,MAAM,UAAU,WAAW,QAAQ;CACnC,MAAM,OAAO,WAAW,SAAS,KAAK;CACtC,IAAI,CAAC,MACH,OAAO,EAAE;CAGX,MAAM,wBAAQ,IAAI,KAAa;CAC/B,KAAK,MAAM,aAAa,QAAQ,oBAAoB,MAAM,kBAAkB,EAAE;EAC5E,MAAM,aAAa,QAAQ,yBAAyB,UAAU;EAC9D,IAAI,CAAC,YACH;EAEF,KAAK,MAAM,QAAQ,CAAC,GAAI,WAAW,SAAS,EAAE,EAAG,QAAQ,aAAa,WAAW,CAAC,EAChF,IAAI,MACF,MAAM,IAAI,KAAK;;CAKrB,MAAM,WAAW,CAAC,GAAG,MAAM;CAC3B,OAAO,SAAS,MAAM,qBAAqB,GAAG,EAAE,GAAG;;AAGrD,SAAS,qBAAqB,MAAuB;CACnD,OAAO,SAAS,SAAS,SAAS,aAAa,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"prefer_promise_reject_errors.js","names":[],"sources":["../../ts/rules/prefer_promise_reject_errors.ts"],"sourcesContent":["import {\n isIdentifierNamed,\n memberObject,\n memberPropertyName,\n nearestFunctionAncestors,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isAnyLikeNode, isErrorLikeNode, isPromiseLikeNode, isUnknownLikeNode } from \"./type_utils\";\n\ntype Options = {\n allowEmptyReject?: boolean;\n allowThrowingAny?: boolean;\n allowThrowingUnknown?: boolean;\n};\n\nconst defaults: Required<Options> = {\n allowEmptyReject: false,\n allowThrowingAny: false,\n allowThrowingUnknown: false,\n};\n\nexport const preferPromiseRejectErrorsRule = createNativeRule(\n \"prefer-promise-reject-errors\",\n {\n docs: {\n description: \"Require Promise rejection reasons to be Error-like values.\",\n },\n messages: {\n rejectAnError: \"Expected the Promise rejection reason to be an Error.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (!isPromiseRejectCall(context, node) && !isPromiseExecutorRejectCall(context, node)) {\n return;\n }\n if (acceptRejectArguments(context, node.arguments, resolveOptions(context.options))) {\n return;\n }\n context.report({ node, messageId: \"rejectAnError\" });\n },\n }),\n);\n\nfunction isPromiseRejectCall(context: any, node: any): boolean {\n const object = memberObject(node.callee) as any;\n return (\n memberPropertyName(node.callee) === \"reject\" &&\n (isIdentifierNamed(object, \"Promise\") || isPromiseLikeNode(context, object))\n );\n}\n\nfunction isPromiseExecutorRejectCall(context: any, node: any): boolean {\n const callee = stripChainExpression(node.callee);\n if (callee?.type !== \"Identifier\") {\n return false;\n }\n const [nearestFunction] = nearestFunctionAncestors(node, context.sourceCode);\n if (!nearestFunction) {\n return false;\n }\n const rejectParam = nearestFunction.params?.[1];\n if (!rejectParam || rejectParam.type !== \"Identifier\" || rejectParam.name !== callee.name) {\n return false;\n }\n const promiseConstructor = stripChainExpression(nearestFunction.parent?.parent);\n return (\n (nearestFunction.parent?.type === \"NewExpression\" &&\n isIdentifierNamed(nearestFunction.parent.callee, \"Promise\")) ||\n (promiseConstructor?.type === \"NewExpression\" &&\n isIdentifierNamed(promiseConstructor.callee, \"Promise\"))\n );\n}\n\nfunction acceptRejectArguments(\n context: any,\n args: readonly any[],\n options: Required<Options>,\n): boolean {\n const [argument] = args;\n if (!argument) {\n return options.allowEmptyReject;\n }\n if (options.allowThrowingAny && isAnyLikeNode(context, argument)) {\n return true;\n }\n if (options.allowThrowingUnknown && isUnknownLikeNode(context, argument)) {\n return true;\n }\n return isErrorLikeNode(context, argument);\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;AAgBA,MAAM,WAA8B;CAClC,kBAAkB;CAClB,kBAAkB;CAClB,sBAAsB;CACvB;AAED,MAAa,gCAAgC,iBAC3C,gCACA;CACE,MAAM,EACJ,aAAa,8DACd;CACD,UAAU,EACR,eAAe,yDAChB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;AACxB,KAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,CAAC,4BAA4B,SAAS,KAAK,CACpF;AAEF,KAAI,sBAAsB,SAAS,KAAK,WAAW,eAAe,QAAQ,QAAQ,CAAC,CACjF;AAEF,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAiB,CAAC;GAEvD,EACF;AAED,SAAS,oBAAoB,SAAc,MAAoB;CAC7D,MAAM,SAAS,aAAa,KAAK,OAAO;AACxC,QACE,mBAAmB,KAAK,OAAO,KAAK,aACnC,kBAAkB,QAAQ,UAAU,IAAI,kBAAkB,SAAS,OAAO;;AAI/E,SAAS,4BAA4B,SAAc,MAAoB;CACrE,MAAM,SAAS,qBAAqB,KAAK,OAAO;AAChD,KAAI,QAAQ,SAAS,aACnB,QAAO;CAET,MAAM,CAAC,mBAAmB,yBAAyB,MAAM,QAAQ,WAAW;AAC5E,KAAI,CAAC,gBACH,QAAO;CAET,MAAM,cAAc,gBAAgB,SAAS;AAC7C,KAAI,CAAC,eAAe,YAAY,SAAS,gBAAgB,YAAY,SAAS,OAAO,KACnF,QAAO;CAET,MAAM,qBAAqB,qBAAqB,gBAAgB,QAAQ,OAAO;AAC/E,QACG,gBAAgB,QAAQ,SAAS,mBAChC,kBAAkB,gBAAgB,OAAO,QAAQ,UAAU,IAC5D,oBAAoB,SAAS,mBAC5B,kBAAkB,mBAAmB,QAAQ,UAAU;;AAI7D,SAAS,sBACP,SACA,MACA,SACS;CACT,MAAM,CAAC,YAAY;AACnB,KAAI,CAAC,SACH,QAAO,QAAQ;AAEjB,KAAI,QAAQ,oBAAoB,cAAc,SAAS,SAAS,CAC9D,QAAO;AAET,KAAI,QAAQ,wBAAwB,kBAAkB,SAAS,SAAS,CACtE,QAAO;AAET,QAAO,gBAAgB,SAAS,SAAS;;AAG3C,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
1
+ {"version":3,"file":"prefer_promise_reject_errors.js","names":[],"sources":["../../ts/rules/prefer_promise_reject_errors.ts"],"sourcesContent":["import {\n isIdentifierNamed,\n memberObject,\n memberPropertyName,\n nearestFunctionAncestors,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isAnyLikeNode, isErrorLikeNode, isPromiseLikeNode, isUnknownLikeNode } from \"./type_utils\";\n\ntype Options = {\n allowEmptyReject?: boolean;\n allowThrowingAny?: boolean;\n allowThrowingUnknown?: boolean;\n};\n\nconst defaults: Required<Options> = {\n allowEmptyReject: false,\n allowThrowingAny: false,\n allowThrowingUnknown: false,\n};\n\nexport const preferPromiseRejectErrorsRule = createNativeRule(\n \"prefer-promise-reject-errors\",\n {\n docs: {\n description: \"Require Promise rejection reasons to be Error-like values.\",\n },\n messages: {\n rejectAnError: \"Expected the Promise rejection reason to be an Error.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (!isPromiseRejectCall(context, node) && !isPromiseExecutorRejectCall(context, node)) {\n return;\n }\n if (acceptRejectArguments(context, node.arguments, resolveOptions(context.options))) {\n return;\n }\n context.report({ node, messageId: \"rejectAnError\" });\n },\n }),\n);\n\nfunction isPromiseRejectCall(context: any, node: any): boolean {\n const object = memberObject(node.callee) as any;\n return (\n memberPropertyName(node.callee) === \"reject\" &&\n (isIdentifierNamed(object, \"Promise\") || isPromiseLikeNode(context, object))\n );\n}\n\nfunction isPromiseExecutorRejectCall(context: any, node: any): boolean {\n const callee = stripChainExpression(node.callee);\n if (callee?.type !== \"Identifier\") {\n return false;\n }\n const [nearestFunction] = nearestFunctionAncestors(node, context.sourceCode);\n if (!nearestFunction) {\n return false;\n }\n const rejectParam = nearestFunction.params?.[1];\n if (!rejectParam || rejectParam.type !== \"Identifier\" || rejectParam.name !== callee.name) {\n return false;\n }\n const promiseConstructor = stripChainExpression(nearestFunction.parent?.parent);\n return (\n (nearestFunction.parent?.type === \"NewExpression\" &&\n isIdentifierNamed(nearestFunction.parent.callee, \"Promise\")) ||\n (promiseConstructor?.type === \"NewExpression\" &&\n isIdentifierNamed(promiseConstructor.callee, \"Promise\"))\n );\n}\n\nfunction acceptRejectArguments(\n context: any,\n args: readonly any[],\n options: Required<Options>,\n): boolean {\n const [argument] = args;\n if (!argument) {\n return options.allowEmptyReject;\n }\n if (options.allowThrowingAny && isAnyLikeNode(context, argument)) {\n return true;\n }\n if (options.allowThrowingUnknown && isUnknownLikeNode(context, argument)) {\n return true;\n }\n return isErrorLikeNode(context, argument);\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;AAgBA,MAAM,WAA8B;CAClC,kBAAkB;CAClB,kBAAkB;CAClB,sBAAsB;CACvB;AAED,MAAa,gCAAgC,iBAC3C,gCACA;CACE,MAAM,EACJ,aAAa,8DACd;CACD,UAAU,EACR,eAAe,yDAChB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;CACxB,IAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,CAAC,4BAA4B,SAAS,KAAK,EACpF;CAEF,IAAI,sBAAsB,SAAS,KAAK,WAAW,eAAe,QAAQ,QAAQ,CAAC,EACjF;CAEF,QAAQ,OAAO;EAAE;EAAM,WAAW;EAAiB,CAAC;GAEvD,EACF;AAED,SAAS,oBAAoB,SAAc,MAAoB;CAC7D,MAAM,SAAS,aAAa,KAAK,OAAO;CACxC,OACE,mBAAmB,KAAK,OAAO,KAAK,aACnC,kBAAkB,QAAQ,UAAU,IAAI,kBAAkB,SAAS,OAAO;;AAI/E,SAAS,4BAA4B,SAAc,MAAoB;CACrE,MAAM,SAAS,qBAAqB,KAAK,OAAO;CAChD,IAAI,QAAQ,SAAS,cACnB,OAAO;CAET,MAAM,CAAC,mBAAmB,yBAAyB,MAAM,QAAQ,WAAW;CAC5E,IAAI,CAAC,iBACH,OAAO;CAET,MAAM,cAAc,gBAAgB,SAAS;CAC7C,IAAI,CAAC,eAAe,YAAY,SAAS,gBAAgB,YAAY,SAAS,OAAO,MACnF,OAAO;CAET,MAAM,qBAAqB,qBAAqB,gBAAgB,QAAQ,OAAO;CAC/E,OACG,gBAAgB,QAAQ,SAAS,mBAChC,kBAAkB,gBAAgB,OAAO,QAAQ,UAAU,IAC5D,oBAAoB,SAAS,mBAC5B,kBAAkB,mBAAmB,QAAQ,UAAU;;AAI7D,SAAS,sBACP,SACA,MACA,SACS;CACT,MAAM,CAAC,YAAY;CACnB,IAAI,CAAC,UACH,OAAO,QAAQ;CAEjB,IAAI,QAAQ,oBAAoB,cAAc,SAAS,SAAS,EAC9D,OAAO;CAET,IAAI,QAAQ,wBAAwB,kBAAkB,SAAS,SAAS,EACtE,OAAO;CAET,OAAO,gBAAgB,SAAS,SAAS;;AAG3C,SAAS,eAAe,SAAgD;CACtE,OAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"prefer_string_starts_ends_with.js","names":[],"sources":["../../ts/rules/prefer_string_starts_ends_with.ts"],"sourcesContent":["import {\n calleePropertyName,\n isZeroLiteral,\n memberObject,\n memberPropertyName,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\n\nconst comparableOperators = new Set([\"==\", \"===\", \"!=\", \"!==\"]);\n\nexport const preferStringStartsEndsWithRule = createNativeRule(\n \"prefer-string-starts-ends-with\",\n {\n docs: {\n description: \"Prefer startsWith()/endsWith() over manual string prefix/suffix checks.\",\n },\n messages: {\n endsWith: \"Use endsWith() instead of slicing and comparing a suffix.\",\n startsWith: \"Use startsWith() instead of comparing a prefix manually.\",\n },\n },\n (context) => ({\n BinaryExpression(node: any) {\n if (!comparableOperators.has(node.operator)) {\n return;\n }\n\n const match =\n detectManualStringCheck(context.sourceCode, node.left, node.right) ??\n detectManualStringCheck(context.sourceCode, node.right, node.left);\n if (!match) {\n return;\n }\n\n context.report({\n node,\n messageId: match,\n });\n },\n }),\n);\n\nfunction detectManualStringCheck(\n sourceCode: any,\n candidate: any,\n compared: any,\n): \"startsWith\" | \"endsWith\" | undefined {\n const current = stripChainExpression(candidate) as any;\n if (current?.type !== \"CallExpression\") {\n return undefined;\n }\n\n if (calleePropertyName(current) === \"indexOf\" && isZeroLiteral(compared)) {\n return \"startsWith\";\n }\n\n if (calleePropertyName(current) !== \"slice\") {\n return undefined;\n }\n\n const [start, end] = current.arguments;\n if (isZeroLiteral(start) && end && sameLengthTarget(end, compared, sourceCode)) {\n return \"startsWith\";\n }\n\n const suffix = negativeLengthTarget(start);\n if (!end && suffix && sameExpression(suffix, compared, sourceCode)) {\n return \"endsWith\";\n }\n\n return undefined;\n}\n\nfunction sameLengthTarget(lengthNode: any, compared: any, sourceCode: any): boolean {\n if (memberPropertyName(lengthNode) !== \"length\") {\n return false;\n }\n const target = memberObject(lengthNode);\n return target ? sameExpression(target, compared, sourceCode) : false;\n}\n\nfunction negativeLengthTarget(node: any): any {\n const current = stripChainExpression(node) as any;\n if (current?.type !== \"UnaryExpression\" || current.operator !== \"-\") {\n return undefined;\n }\n const target = memberObject(current.argument);\n if (!target || memberPropertyName(current.argument) !== \"length\") {\n return undefined;\n }\n return target;\n}\n\nfunction sameExpression(left: any, right: any, sourceCode: any): boolean {\n return (\n sourceCode.getText(stripChainExpression(left)) ===\n sourceCode.getText(stripChainExpression(right))\n );\n}\n"],"mappings":";;;AASA,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAM;CAAO;CAAM;CAAM,CAAC;AAE/D,MAAa,iCAAiC,iBAC5C,kCACA;CACE,MAAM,EACJ,aAAa,2EACd;CACD,UAAU;EACR,UAAU;EACV,YAAY;EACb;CACF,GACA,aAAa,EACZ,iBAAiB,MAAW;AAC1B,KAAI,CAAC,oBAAoB,IAAI,KAAK,SAAS,CACzC;CAGF,MAAM,QACJ,wBAAwB,QAAQ,YAAY,KAAK,MAAM,KAAK,MAAM,IAClE,wBAAwB,QAAQ,YAAY,KAAK,OAAO,KAAK,KAAK;AACpE,KAAI,CAAC,MACH;AAGF,SAAQ,OAAO;EACb;EACA,WAAW;EACZ,CAAC;GAEL,EACF;AAED,SAAS,wBACP,YACA,WACA,UACuC;CACvC,MAAM,UAAU,qBAAqB,UAAU;AAC/C,KAAI,SAAS,SAAS,iBACpB;AAGF,KAAI,mBAAmB,QAAQ,KAAK,aAAa,cAAc,SAAS,CACtE,QAAO;AAGT,KAAI,mBAAmB,QAAQ,KAAK,QAClC;CAGF,MAAM,CAAC,OAAO,OAAO,QAAQ;AAC7B,KAAI,cAAc,MAAM,IAAI,OAAO,iBAAiB,KAAK,UAAU,WAAW,CAC5E,QAAO;CAGT,MAAM,SAAS,qBAAqB,MAAM;AAC1C,KAAI,CAAC,OAAO,UAAU,eAAe,QAAQ,UAAU,WAAW,CAChE,QAAO;;AAMX,SAAS,iBAAiB,YAAiB,UAAe,YAA0B;AAClF,KAAI,mBAAmB,WAAW,KAAK,SACrC,QAAO;CAET,MAAM,SAAS,aAAa,WAAW;AACvC,QAAO,SAAS,eAAe,QAAQ,UAAU,WAAW,GAAG;;AAGjE,SAAS,qBAAqB,MAAgB;CAC5C,MAAM,UAAU,qBAAqB,KAAK;AAC1C,KAAI,SAAS,SAAS,qBAAqB,QAAQ,aAAa,IAC9D;CAEF,MAAM,SAAS,aAAa,QAAQ,SAAS;AAC7C,KAAI,CAAC,UAAU,mBAAmB,QAAQ,SAAS,KAAK,SACtD;AAEF,QAAO;;AAGT,SAAS,eAAe,MAAW,OAAY,YAA0B;AACvE,QACE,WAAW,QAAQ,qBAAqB,KAAK,CAAC,KAC9C,WAAW,QAAQ,qBAAqB,MAAM,CAAC"}
1
+ {"version":3,"file":"prefer_string_starts_ends_with.js","names":[],"sources":["../../ts/rules/prefer_string_starts_ends_with.ts"],"sourcesContent":["import {\n calleePropertyName,\n isZeroLiteral,\n memberObject,\n memberPropertyName,\n stripChainExpression,\n} from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\n\nconst comparableOperators = new Set([\"==\", \"===\", \"!=\", \"!==\"]);\n\nexport const preferStringStartsEndsWithRule = createNativeRule(\n \"prefer-string-starts-ends-with\",\n {\n docs: {\n description: \"Prefer startsWith()/endsWith() over manual string prefix/suffix checks.\",\n },\n messages: {\n endsWith: \"Use endsWith() instead of slicing and comparing a suffix.\",\n startsWith: \"Use startsWith() instead of comparing a prefix manually.\",\n },\n },\n (context) => ({\n BinaryExpression(node: any) {\n if (!comparableOperators.has(node.operator)) {\n return;\n }\n\n const match =\n detectManualStringCheck(context.sourceCode, node.left, node.right) ??\n detectManualStringCheck(context.sourceCode, node.right, node.left);\n if (!match) {\n return;\n }\n\n context.report({\n node,\n messageId: match,\n });\n },\n }),\n);\n\nfunction detectManualStringCheck(\n sourceCode: any,\n candidate: any,\n compared: any,\n): \"startsWith\" | \"endsWith\" | undefined {\n const current = stripChainExpression(candidate) as any;\n if (current?.type !== \"CallExpression\") {\n return undefined;\n }\n\n if (calleePropertyName(current) === \"indexOf\" && isZeroLiteral(compared)) {\n return \"startsWith\";\n }\n\n if (calleePropertyName(current) !== \"slice\") {\n return undefined;\n }\n\n const [start, end] = current.arguments;\n if (isZeroLiteral(start) && end && sameLengthTarget(end, compared, sourceCode)) {\n return \"startsWith\";\n }\n\n const suffix = negativeLengthTarget(start);\n if (!end && suffix && sameExpression(suffix, compared, sourceCode)) {\n return \"endsWith\";\n }\n\n return undefined;\n}\n\nfunction sameLengthTarget(lengthNode: any, compared: any, sourceCode: any): boolean {\n if (memberPropertyName(lengthNode) !== \"length\") {\n return false;\n }\n const target = memberObject(lengthNode);\n return target ? sameExpression(target, compared, sourceCode) : false;\n}\n\nfunction negativeLengthTarget(node: any): any {\n const current = stripChainExpression(node) as any;\n if (current?.type !== \"UnaryExpression\" || current.operator !== \"-\") {\n return undefined;\n }\n const target = memberObject(current.argument);\n if (!target || memberPropertyName(current.argument) !== \"length\") {\n return undefined;\n }\n return target;\n}\n\nfunction sameExpression(left: any, right: any, sourceCode: any): boolean {\n return (\n sourceCode.getText(stripChainExpression(left)) ===\n sourceCode.getText(stripChainExpression(right))\n );\n}\n"],"mappings":";;;AASA,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAM;CAAO;CAAM;CAAM,CAAC;AAE/D,MAAa,iCAAiC,iBAC5C,kCACA;CACE,MAAM,EACJ,aAAa,2EACd;CACD,UAAU;EACR,UAAU;EACV,YAAY;EACb;CACF,GACA,aAAa,EACZ,iBAAiB,MAAW;CAC1B,IAAI,CAAC,oBAAoB,IAAI,KAAK,SAAS,EACzC;CAGF,MAAM,QACJ,wBAAwB,QAAQ,YAAY,KAAK,MAAM,KAAK,MAAM,IAClE,wBAAwB,QAAQ,YAAY,KAAK,OAAO,KAAK,KAAK;CACpE,IAAI,CAAC,OACH;CAGF,QAAQ,OAAO;EACb;EACA,WAAW;EACZ,CAAC;GAEL,EACF;AAED,SAAS,wBACP,YACA,WACA,UACuC;CACvC,MAAM,UAAU,qBAAqB,UAAU;CAC/C,IAAI,SAAS,SAAS,kBACpB;CAGF,IAAI,mBAAmB,QAAQ,KAAK,aAAa,cAAc,SAAS,EACtE,OAAO;CAGT,IAAI,mBAAmB,QAAQ,KAAK,SAClC;CAGF,MAAM,CAAC,OAAO,OAAO,QAAQ;CAC7B,IAAI,cAAc,MAAM,IAAI,OAAO,iBAAiB,KAAK,UAAU,WAAW,EAC5E,OAAO;CAGT,MAAM,SAAS,qBAAqB,MAAM;CAC1C,IAAI,CAAC,OAAO,UAAU,eAAe,QAAQ,UAAU,WAAW,EAChE,OAAO;;AAMX,SAAS,iBAAiB,YAAiB,UAAe,YAA0B;CAClF,IAAI,mBAAmB,WAAW,KAAK,UACrC,OAAO;CAET,MAAM,SAAS,aAAa,WAAW;CACvC,OAAO,SAAS,eAAe,QAAQ,UAAU,WAAW,GAAG;;AAGjE,SAAS,qBAAqB,MAAgB;CAC5C,MAAM,UAAU,qBAAqB,KAAK;CAC1C,IAAI,SAAS,SAAS,qBAAqB,QAAQ,aAAa,KAC9D;CAEF,MAAM,SAAS,aAAa,QAAQ,SAAS;CAC7C,IAAI,CAAC,UAAU,mBAAmB,QAAQ,SAAS,KAAK,UACtD;CAEF,OAAO;;AAGT,SAAS,eAAe,MAAW,OAAY,YAA0B;CACvE,OACE,WAAW,QAAQ,qBAAqB,KAAK,CAAC,KAC9C,WAAW,QAAQ,qBAAqB,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"require_array_sort_compare.js","names":[],"sources":["../../ts/rules/require_array_sort_compare.ts"],"sourcesContent":["import { memberObject, memberPropertyName } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isArrayLikeNode, typeTextsAtNode } from \"./type_utils\";\nimport { isStringArrayLikeTypeTexts } from \"../utils\";\n\ntype Options = {\n ignoreStringArrays?: boolean;\n};\n\nconst defaults: Required<Options> = {\n ignoreStringArrays: true,\n};\n\nexport const requireArraySortCompareRule = createNativeRule(\n \"require-array-sort-compare\",\n {\n docs: {\n description: \"Require compare callbacks for array sorting calls.\",\n },\n messages: {\n requireCompare: \"Require a compare argument for array sorting.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (node.arguments.length !== 0) {\n return;\n }\n const methodName = memberPropertyName(node.callee);\n if (methodName !== \"sort\" && methodName !== \"toSorted\") {\n return;\n }\n const object = memberObject(node.callee) as any;\n if (!object || !isArrayLikeNode(context, object)) {\n return;\n }\n if (\n resolveOptions(context.options).ignoreStringArrays &&\n isStringArrayLike(context, object)\n ) {\n return;\n }\n context.report({ node, messageId: \"requireCompare\" });\n },\n }),\n);\n\nfunction isStringArrayLike(context: any, node: any): boolean {\n return isStringArrayLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;;AASA,MAAM,WAA8B,EAClC,oBAAoB,MACrB;AAED,MAAa,8BAA8B,iBACzC,8BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU,EACR,gBAAgB,iDACjB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;AACxB,KAAI,KAAK,UAAU,WAAW,EAC5B;CAEF,MAAM,aAAa,mBAAmB,KAAK,OAAO;AAClD,KAAI,eAAe,UAAU,eAAe,WAC1C;CAEF,MAAM,SAAS,aAAa,KAAK,OAAO;AACxC,KAAI,CAAC,UAAU,CAAC,gBAAgB,SAAS,OAAO,CAC9C;AAEF,KACE,eAAe,QAAQ,QAAQ,CAAC,sBAChC,kBAAkB,SAAS,OAAO,CAElC;AAEF,SAAQ,OAAO;EAAE;EAAM,WAAW;EAAkB,CAAC;GAExD,EACF;AAED,SAAS,kBAAkB,SAAc,MAAoB;AAC3D,QAAO,2BAA2B,gBAAgB,SAAS,KAAK,CAAC;;AAGnE,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
1
+ {"version":3,"file":"require_array_sort_compare.js","names":[],"sources":["../../ts/rules/require_array_sort_compare.ts"],"sourcesContent":["import { memberObject, memberPropertyName } from \"./ast\";\nimport { createNativeRule } from \"./rule_creator\";\nimport { isArrayLikeNode, typeTextsAtNode } from \"./type_utils\";\nimport { isStringArrayLikeTypeTexts } from \"../utils\";\n\ntype Options = {\n ignoreStringArrays?: boolean;\n};\n\nconst defaults: Required<Options> = {\n ignoreStringArrays: true,\n};\n\nexport const requireArraySortCompareRule = createNativeRule(\n \"require-array-sort-compare\",\n {\n docs: {\n description: \"Require compare callbacks for array sorting calls.\",\n },\n messages: {\n requireCompare: \"Require a compare argument for array sorting.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n CallExpression(node: any) {\n if (node.arguments.length !== 0) {\n return;\n }\n const methodName = memberPropertyName(node.callee);\n if (methodName !== \"sort\" && methodName !== \"toSorted\") {\n return;\n }\n const object = memberObject(node.callee) as any;\n if (!object || !isArrayLikeNode(context, object)) {\n return;\n }\n if (\n resolveOptions(context.options).ignoreStringArrays &&\n isStringArrayLike(context, object)\n ) {\n return;\n }\n context.report({ node, messageId: \"requireCompare\" });\n },\n }),\n);\n\nfunction isStringArrayLike(context: any, node: any): boolean {\n return isStringArrayLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;;;AASA,MAAM,WAA8B,EAClC,oBAAoB,MACrB;AAED,MAAa,8BAA8B,iBACzC,8BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU,EACR,gBAAgB,iDACjB;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa,EACZ,eAAe,MAAW;CACxB,IAAI,KAAK,UAAU,WAAW,GAC5B;CAEF,MAAM,aAAa,mBAAmB,KAAK,OAAO;CAClD,IAAI,eAAe,UAAU,eAAe,YAC1C;CAEF,MAAM,SAAS,aAAa,KAAK,OAAO;CACxC,IAAI,CAAC,UAAU,CAAC,gBAAgB,SAAS,OAAO,EAC9C;CAEF,IACE,eAAe,QAAQ,QAAQ,CAAC,sBAChC,kBAAkB,SAAS,OAAO,EAElC;CAEF,QAAQ,OAAO;EAAE;EAAM,WAAW;EAAkB,CAAC;GAExD,EACF;AAED,SAAS,kBAAkB,SAAc,MAAoB;CAC3D,OAAO,2BAA2B,gBAAgB,SAAS,KAAK,CAAC;;AAGnE,SAAS,eAAe,SAAgD;CACtE,OAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"restrict_plus_operands.js","names":[],"sources":["../../ts/rules/restrict_plus_operands.ts"],"sourcesContent":["import { createNativeRule } from \"./rule_creator\";\nimport { classifyTypeText, typeTextAtNode } from \"./type_utils\";\n\ntype Options = {\n allowAny?: boolean;\n allowBoolean?: boolean;\n allowNullish?: boolean;\n allowNumberAndString?: boolean;\n allowRegExp?: boolean;\n skipCompoundAssignments?: boolean;\n};\n\nconst defaults: Required<Options> = {\n allowAny: true,\n allowBoolean: true,\n allowNullish: true,\n allowNumberAndString: true,\n allowRegExp: false,\n skipCompoundAssignments: false,\n};\n\nexport const restrictPlusOperandsRule = createNativeRule(\n \"restrict-plus-operands\",\n {\n docs: {\n description: \"Require plus operands to be explicitly compatible.\",\n },\n messages: {\n invalid: \"Operands of + must be compatible primitive values.\",\n mismatched: \"Operands of + operations must be of the same type.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n AssignmentExpression(node: any) {\n const options = resolveOptions(context.options);\n if (options.skipCompoundAssignments || node.operator !== \"+=\") {\n return;\n }\n reportIfInvalid(context, node, node.left, node.right, options);\n },\n BinaryExpression(node: any) {\n if (node.operator !== \"+\") {\n return;\n }\n reportIfInvalid(context, node, node.left, node.right, resolveOptions(context.options));\n },\n }),\n);\n\nfunction reportIfInvalid(\n context: any,\n node: any,\n left: any,\n right: any,\n options: Required<Options>,\n) {\n const leftKind = classifyTypeText(typeTextAtNode(context, left));\n const rightKind = classifyTypeText(typeTextAtNode(context, right));\n if (isAllowed(leftKind, rightKind, options)) {\n return;\n }\n context.report({\n node,\n messageId:\n leftKind === \"other\" ||\n rightKind === \"other\" ||\n leftKind === \"unknown\" ||\n rightKind === \"unknown\"\n ? \"invalid\"\n : \"mismatched\",\n });\n}\n\nfunction isAllowed(\n leftKind: ReturnType<typeof classifyTypeText>,\n rightKind: ReturnType<typeof classifyTypeText>,\n options: Required<Options>,\n): boolean {\n if (leftKind === rightKind && [\"bigint\", \"number\", \"string\"].includes(leftKind)) {\n return true;\n }\n if (\n options.allowNumberAndString &&\n ((leftKind === \"string\" && rightKind === \"number\") ||\n (leftKind === \"number\" && rightKind === \"string\"))\n ) {\n return true;\n }\n if (leftKind === \"string\" && isStringCompanion(rightKind, options)) {\n return true;\n }\n if (rightKind === \"string\" && isStringCompanion(leftKind, options)) {\n return true;\n }\n return false;\n}\n\nfunction isStringCompanion(\n kind: ReturnType<typeof classifyTypeText>,\n options: Required<Options>,\n): boolean {\n return (\n (kind === \"any\" && options.allowAny) ||\n (kind === \"boolean\" && options.allowBoolean) ||\n (kind === \"nullish\" && options.allowNullish) ||\n (kind === \"regexp\" && options.allowRegExp)\n );\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;AAYA,MAAM,WAA8B;CAClC,UAAU;CACV,cAAc;CACd,cAAc;CACd,sBAAsB;CACtB,aAAa;CACb,yBAAyB;CAC1B;AAED,MAAa,2BAA2B,iBACtC,0BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU;EACR,SAAS;EACT,YAAY;EACb;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa;CACZ,qBAAqB,MAAW;EAC9B,MAAM,UAAU,eAAe,QAAQ,QAAQ;AAC/C,MAAI,QAAQ,2BAA2B,KAAK,aAAa,KACvD;AAEF,kBAAgB,SAAS,MAAM,KAAK,MAAM,KAAK,OAAO,QAAQ;;CAEhE,iBAAiB,MAAW;AAC1B,MAAI,KAAK,aAAa,IACpB;AAEF,kBAAgB,SAAS,MAAM,KAAK,MAAM,KAAK,OAAO,eAAe,QAAQ,QAAQ,CAAC;;CAEzF,EACF;AAED,SAAS,gBACP,SACA,MACA,MACA,OACA,SACA;CACA,MAAM,WAAW,iBAAiB,eAAe,SAAS,KAAK,CAAC;CAChE,MAAM,YAAY,iBAAiB,eAAe,SAAS,MAAM,CAAC;AAClE,KAAI,UAAU,UAAU,WAAW,QAAQ,CACzC;AAEF,SAAQ,OAAO;EACb;EACA,WACE,aAAa,WACb,cAAc,WACd,aAAa,aACb,cAAc,YACV,YACA;EACP,CAAC;;AAGJ,SAAS,UACP,UACA,WACA,SACS;AACT,KAAI,aAAa,aAAa;EAAC;EAAU;EAAU;EAAS,CAAC,SAAS,SAAS,CAC7E,QAAO;AAET,KACE,QAAQ,yBACN,aAAa,YAAY,cAAc,YACtC,aAAa,YAAY,cAAc,UAE1C,QAAO;AAET,KAAI,aAAa,YAAY,kBAAkB,WAAW,QAAQ,CAChE,QAAO;AAET,KAAI,cAAc,YAAY,kBAAkB,UAAU,QAAQ,CAChE,QAAO;AAET,QAAO;;AAGT,SAAS,kBACP,MACA,SACS;AACT,QACG,SAAS,SAAS,QAAQ,YAC1B,SAAS,aAAa,QAAQ,gBAC9B,SAAS,aAAa,QAAQ,gBAC9B,SAAS,YAAY,QAAQ;;AAIlC,SAAS,eAAe,SAAgD;AACtE,QAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
1
+ {"version":3,"file":"restrict_plus_operands.js","names":[],"sources":["../../ts/rules/restrict_plus_operands.ts"],"sourcesContent":["import { createNativeRule } from \"./rule_creator\";\nimport { classifyTypeText, typeTextAtNode } from \"./type_utils\";\n\ntype Options = {\n allowAny?: boolean;\n allowBoolean?: boolean;\n allowNullish?: boolean;\n allowNumberAndString?: boolean;\n allowRegExp?: boolean;\n skipCompoundAssignments?: boolean;\n};\n\nconst defaults: Required<Options> = {\n allowAny: true,\n allowBoolean: true,\n allowNullish: true,\n allowNumberAndString: true,\n allowRegExp: false,\n skipCompoundAssignments: false,\n};\n\nexport const restrictPlusOperandsRule = createNativeRule(\n \"restrict-plus-operands\",\n {\n docs: {\n description: \"Require plus operands to be explicitly compatible.\",\n },\n messages: {\n invalid: \"Operands of + must be compatible primitive values.\",\n mismatched: \"Operands of + operations must be of the same type.\",\n },\n schema: { type: \"array\" },\n },\n (context) => ({\n AssignmentExpression(node: any) {\n const options = resolveOptions(context.options);\n if (options.skipCompoundAssignments || node.operator !== \"+=\") {\n return;\n }\n reportIfInvalid(context, node, node.left, node.right, options);\n },\n BinaryExpression(node: any) {\n if (node.operator !== \"+\") {\n return;\n }\n reportIfInvalid(context, node, node.left, node.right, resolveOptions(context.options));\n },\n }),\n);\n\nfunction reportIfInvalid(\n context: any,\n node: any,\n left: any,\n right: any,\n options: Required<Options>,\n) {\n const leftKind = classifyTypeText(typeTextAtNode(context, left));\n const rightKind = classifyTypeText(typeTextAtNode(context, right));\n if (isAllowed(leftKind, rightKind, options)) {\n return;\n }\n context.report({\n node,\n messageId:\n leftKind === \"other\" ||\n rightKind === \"other\" ||\n leftKind === \"unknown\" ||\n rightKind === \"unknown\"\n ? \"invalid\"\n : \"mismatched\",\n });\n}\n\nfunction isAllowed(\n leftKind: ReturnType<typeof classifyTypeText>,\n rightKind: ReturnType<typeof classifyTypeText>,\n options: Required<Options>,\n): boolean {\n if (leftKind === rightKind && [\"bigint\", \"number\", \"string\"].includes(leftKind)) {\n return true;\n }\n if (\n options.allowNumberAndString &&\n ((leftKind === \"string\" && rightKind === \"number\") ||\n (leftKind === \"number\" && rightKind === \"string\"))\n ) {\n return true;\n }\n if (leftKind === \"string\" && isStringCompanion(rightKind, options)) {\n return true;\n }\n if (rightKind === \"string\" && isStringCompanion(leftKind, options)) {\n return true;\n }\n return false;\n}\n\nfunction isStringCompanion(\n kind: ReturnType<typeof classifyTypeText>,\n options: Required<Options>,\n): boolean {\n return (\n (kind === \"any\" && options.allowAny) ||\n (kind === \"boolean\" && options.allowBoolean) ||\n (kind === \"nullish\" && options.allowNullish) ||\n (kind === \"regexp\" && options.allowRegExp)\n );\n}\n\nfunction resolveOptions(options: readonly unknown[]): Required<Options> {\n return { ...defaults, ...(options[0] as Options | undefined) };\n}\n"],"mappings":";;;AAYA,MAAM,WAA8B;CAClC,UAAU;CACV,cAAc;CACd,cAAc;CACd,sBAAsB;CACtB,aAAa;CACb,yBAAyB;CAC1B;AAED,MAAa,2BAA2B,iBACtC,0BACA;CACE,MAAM,EACJ,aAAa,sDACd;CACD,UAAU;EACR,SAAS;EACT,YAAY;EACb;CACD,QAAQ,EAAE,MAAM,SAAS;CAC1B,GACA,aAAa;CACZ,qBAAqB,MAAW;EAC9B,MAAM,UAAU,eAAe,QAAQ,QAAQ;EAC/C,IAAI,QAAQ,2BAA2B,KAAK,aAAa,MACvD;EAEF,gBAAgB,SAAS,MAAM,KAAK,MAAM,KAAK,OAAO,QAAQ;;CAEhE,iBAAiB,MAAW;EAC1B,IAAI,KAAK,aAAa,KACpB;EAEF,gBAAgB,SAAS,MAAM,KAAK,MAAM,KAAK,OAAO,eAAe,QAAQ,QAAQ,CAAC;;CAEzF,EACF;AAED,SAAS,gBACP,SACA,MACA,MACA,OACA,SACA;CACA,MAAM,WAAW,iBAAiB,eAAe,SAAS,KAAK,CAAC;CAChE,MAAM,YAAY,iBAAiB,eAAe,SAAS,MAAM,CAAC;CAClE,IAAI,UAAU,UAAU,WAAW,QAAQ,EACzC;CAEF,QAAQ,OAAO;EACb;EACA,WACE,aAAa,WACb,cAAc,WACd,aAAa,aACb,cAAc,YACV,YACA;EACP,CAAC;;AAGJ,SAAS,UACP,UACA,WACA,SACS;CACT,IAAI,aAAa,aAAa;EAAC;EAAU;EAAU;EAAS,CAAC,SAAS,SAAS,EAC7E,OAAO;CAET,IACE,QAAQ,yBACN,aAAa,YAAY,cAAc,YACtC,aAAa,YAAY,cAAc,WAE1C,OAAO;CAET,IAAI,aAAa,YAAY,kBAAkB,WAAW,QAAQ,EAChE,OAAO;CAET,IAAI,cAAc,YAAY,kBAAkB,UAAU,QAAQ,EAChE,OAAO;CAET,OAAO;;AAGT,SAAS,kBACP,MACA,SACS;CACT,OACG,SAAS,SAAS,QAAQ,YAC1B,SAAS,aAAa,QAAQ,gBAC9B,SAAS,aAAa,QAAQ,gBAC9B,SAAS,YAAY,QAAQ;;AAIlC,SAAS,eAAe,SAAgD;CACtE,OAAO;EAAE,GAAG;EAAU,GAAI,QAAQ;EAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"rule_creator.js","names":[],"sources":["../../ts/rules/rule_creator.ts"],"sourcesContent":["import { defineRule } from \"../plugin\";\n\nexport function createNativeRule(\n name: string,\n meta: Record<string, unknown>,\n create: (context: any) => Record<string, (node: any) => void>,\n) {\n return defineRule({\n defaultOptions: [],\n meta: {\n type: \"problem\",\n schema: [],\n ...meta,\n docs: {\n requiresTypeChecking: true,\n url: `https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint/ts/rules/${name.replaceAll(\"-\", \"_\")}.ts`,\n ...(meta.docs as object | undefined),\n },\n },\n create,\n });\n}\n"],"mappings":";;AAEA,SAAgB,iBACd,MACA,MACA,QACA;AACA,QAAO,WAAW;EAChB,gBAAgB,EAAE;EAClB,MAAM;GACJ,MAAM;GACN,QAAQ,EAAE;GACV,GAAG;GACH,MAAM;IACJ,sBAAsB;IACtB,KAAK,mGAAmG,KAAK,WAAW,KAAK,IAAI,CAAC;IAClI,GAAI,KAAK;IACV;GACF;EACD;EACD,CAAC"}
1
+ {"version":3,"file":"rule_creator.js","names":[],"sources":["../../ts/rules/rule_creator.ts"],"sourcesContent":["import { defineRule } from \"../plugin\";\n\nexport function createNativeRule(\n name: string,\n meta: Record<string, unknown>,\n create: (context: any) => Record<string, (node: any) => void>,\n) {\n return defineRule({\n defaultOptions: [],\n meta: {\n type: \"problem\",\n schema: [],\n ...meta,\n docs: {\n requiresTypeChecking: true,\n url: `https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint/ts/rules/${name.replaceAll(\"-\", \"_\")}.ts`,\n ...(meta.docs as object | undefined),\n },\n },\n create,\n });\n}\n"],"mappings":";;AAEA,SAAgB,iBACd,MACA,MACA,QACA;CACA,OAAO,WAAW;EAChB,gBAAgB,EAAE;EAClB,MAAM;GACJ,MAAM;GACN,QAAQ,EAAE;GACV,GAAG;GACH,MAAM;IACJ,sBAAsB;IACtB,KAAK,mGAAmG,KAAK,WAAW,KAAK,IAAI,CAAC;IAClI,GAAI,KAAK;IACV;GACF;EACD;EACD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"type_utils.js","names":["classifyTypeTextFromRust","splitTopLevelTypeTextFromRust","splitTypeTextFromRust"],"sources":["../../ts/rules/type_utils.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport { OxlintUtils } from \"../oxlint_utils\";\nimport {\n classifyTypeText as classifyTypeTextFromRust,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText as splitTopLevelTypeTextFromRust,\n splitTypeText as splitTypeTextFromRust,\n} from \"../utils\";\nimport { isIdentifierNamed, memberPropertyName, stripChainExpression } from \"./ast\";\nimport type { ContextWithParserOptions, TsgoType, TsgoTypeCheckerShape } from \"../types\";\n\nexport function checkerFor(context: ContextWithParserOptions): TsgoTypeCheckerShape {\n return OxlintUtils.getParserServices(context).program.getTypeChecker();\n}\n\nexport function typeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n return checkerFor(context).getTypeAtLocation(node as Node);\n}\n\nexport function baseTypeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n const type = typeAtNode(context, node);\n if (!type) {\n return undefined;\n }\n return checkerFor(context).getBaseTypeOfLiteralType(type) ?? type;\n}\n\nexport function symbolTypeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n const checker = checkerFor(context);\n const symbol = checker.getSymbolAtLocation(node as Node);\n if (!symbol) {\n return undefined;\n }\n return checker.getTypeOfSymbol(symbol) ?? checker.getDeclaredTypeOfSymbol(symbol);\n}\n\nexport function typeTextAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): string | undefined {\n const type = baseTypeAtNode(context, node);\n return type ? checkerFor(context).typeToString(type) : undefined;\n}\n\nexport function symbolTypeTextAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): string | undefined {\n const type = symbolTypeAtNode(context, node);\n if (!type) {\n return undefined;\n }\n const checker = checkerFor(context);\n return checker.typeToString(checker.getBaseTypeOfLiteralType(type) ?? type);\n}\n\nexport function propertyNamesOfNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): readonly string[] {\n const checker = checkerFor(context);\n const names = new Set<string>();\n for (const type of [baseTypeAtNode(context, node), symbolTypeAtNode(context, node)]) {\n if (!type) {\n continue;\n }\n for (const property of checker.getPropertiesOfType(type)) {\n names.add(property.name);\n }\n }\n return [...names];\n}\n\nexport function isPromiseLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"NewExpression\" && isIdentifierNamed(current.callee, \"Promise\")) {\n return true;\n }\n if (\n current?.type === \"CallExpression\" &&\n memberPropertyName(current.callee) === \"resolve\" &&\n isIdentifierNamed((current.callee as any).object, \"Promise\")\n ) {\n return true;\n }\n return isPromiseLikeTypeTexts(\n [typeTextAtNode(context, node), symbolTypeTextAtNode(context, node)].filter(\n (text): text is string => Boolean(text),\n ),\n propertyNamesOfNode(context, node),\n );\n}\n\nexport function isArrayLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"ArrayExpression\") {\n return true;\n }\n return isArrayLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isStringLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isStringLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isErrorLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"NewExpression\") {\n const callee = stripChainExpression(current.callee);\n const identifier = callee?.type === \"Identifier\" ? callee.name : memberPropertyName(callee);\n if (identifier?.endsWith(\"Error\")) {\n return true;\n }\n }\n return isErrorLikeTypeTexts(typeTextsAtNode(context, node), propertyNamesOfNode(context, node));\n}\n\nexport function isNumberLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isNumberLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isBigIntLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isBigIntLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isAnyLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"TSAsExpression\" && current.typeAnnotation?.type === \"TSAnyKeyword\") {\n return true;\n }\n return isAnyLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isUnknownLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"TSAsExpression\" && current.typeAnnotation?.type === \"TSUnknownKeyword\") {\n return true;\n }\n return isUnknownLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function typeTextsAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): readonly string[] {\n const values = new Set<string>();\n const checker = checkerFor(context);\n collectTexts(baseTypeAtNode(context, node));\n collectTexts(symbolTypeAtNode(context, node));\n return [...values];\n\n function collectTexts(type: TsgoType | undefined): void {\n if (!type) {\n return;\n }\n const texts = Array.isArray(type.texts) ? type.texts : [];\n for (const text of [...texts, checker.typeToString(type)]) {\n if (text) {\n values.add(text);\n }\n }\n }\n}\n\nexport function classifyTypeText(\n text: string | undefined,\n): \"any\" | \"bigint\" | \"boolean\" | \"nullish\" | \"number\" | \"regexp\" | \"string\" | \"unknown\" | \"other\" {\n return classifyTypeTextFromRust(text);\n}\n\nexport function splitTopLevelTypeText(text: string, delimiter: \"|\" | \"&\" | \",\"): readonly string[] {\n return splitTopLevelTypeTextFromRust(text, delimiter);\n}\n\nexport function splitTypeText(text: string): readonly string[] {\n return splitTypeTextFromRust(text);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"type_utils.js","names":["classifyTypeTextFromRust","splitTopLevelTypeTextFromRust","splitTypeTextFromRust"],"sources":["../../ts/rules/type_utils.ts"],"sourcesContent":["import type { Node } from \"@oxlint/plugins\";\n\nimport { OxlintUtils } from \"../oxlint_utils\";\nimport {\n classifyTypeText as classifyTypeTextFromRust,\n isAnyLikeTypeTexts,\n isArrayLikeTypeTexts,\n isBigIntLikeTypeTexts,\n isErrorLikeTypeTexts,\n isNumberLikeTypeTexts,\n isPromiseLikeTypeTexts,\n isStringLikeTypeTexts,\n isUnknownLikeTypeTexts,\n splitTopLevelTypeText as splitTopLevelTypeTextFromRust,\n splitTypeText as splitTypeTextFromRust,\n} from \"../utils\";\nimport { isIdentifierNamed, memberPropertyName, stripChainExpression } from \"./ast\";\nimport type { ContextWithParserOptions, TsgoType, TsgoTypeCheckerShape } from \"../types\";\n\nexport function checkerFor(context: ContextWithParserOptions): TsgoTypeCheckerShape {\n return OxlintUtils.getParserServices(context).program.getTypeChecker();\n}\n\nexport function typeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n return checkerFor(context).getTypeAtLocation(node as Node);\n}\n\nexport function baseTypeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n const type = typeAtNode(context, node);\n if (!type) {\n return undefined;\n }\n return checkerFor(context).getBaseTypeOfLiteralType(type) ?? type;\n}\n\nexport function symbolTypeAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): TsgoType | undefined {\n const checker = checkerFor(context);\n const symbol = checker.getSymbolAtLocation(node as Node);\n if (!symbol) {\n return undefined;\n }\n return checker.getTypeOfSymbol(symbol) ?? checker.getDeclaredTypeOfSymbol(symbol);\n}\n\nexport function typeTextAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): string | undefined {\n const type = baseTypeAtNode(context, node);\n return type ? checkerFor(context).typeToString(type) : undefined;\n}\n\nexport function symbolTypeTextAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): string | undefined {\n const type = symbolTypeAtNode(context, node);\n if (!type) {\n return undefined;\n }\n const checker = checkerFor(context);\n return checker.typeToString(checker.getBaseTypeOfLiteralType(type) ?? type);\n}\n\nexport function propertyNamesOfNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): readonly string[] {\n const checker = checkerFor(context);\n const names = new Set<string>();\n for (const type of [baseTypeAtNode(context, node), symbolTypeAtNode(context, node)]) {\n if (!type) {\n continue;\n }\n for (const property of checker.getPropertiesOfType(type)) {\n names.add(property.name);\n }\n }\n return [...names];\n}\n\nexport function isPromiseLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"NewExpression\" && isIdentifierNamed(current.callee, \"Promise\")) {\n return true;\n }\n if (\n current?.type === \"CallExpression\" &&\n memberPropertyName(current.callee) === \"resolve\" &&\n isIdentifierNamed((current.callee as any).object, \"Promise\")\n ) {\n return true;\n }\n return isPromiseLikeTypeTexts(\n [typeTextAtNode(context, node), symbolTypeTextAtNode(context, node)].filter(\n (text): text is string => Boolean(text),\n ),\n propertyNamesOfNode(context, node),\n );\n}\n\nexport function isArrayLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"ArrayExpression\") {\n return true;\n }\n return isArrayLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isStringLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isStringLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isErrorLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"NewExpression\") {\n const callee = stripChainExpression(current.callee);\n const identifier = callee?.type === \"Identifier\" ? callee.name : memberPropertyName(callee);\n if (identifier?.endsWith(\"Error\")) {\n return true;\n }\n }\n return isErrorLikeTypeTexts(typeTextsAtNode(context, node), propertyNamesOfNode(context, node));\n}\n\nexport function isNumberLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isNumberLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isBigIntLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n return isBigIntLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isAnyLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"TSAsExpression\" && current.typeAnnotation?.type === \"TSAnyKeyword\") {\n return true;\n }\n return isAnyLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function isUnknownLikeNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): boolean {\n const current = stripChainExpression(node as any) as any;\n if (current?.type === \"TSAsExpression\" && current.typeAnnotation?.type === \"TSUnknownKeyword\") {\n return true;\n }\n return isUnknownLikeTypeTexts(typeTextsAtNode(context, node));\n}\n\nexport function typeTextsAtNode(\n context: ContextWithParserOptions,\n node: Node | { readonly range: readonly [number, number] },\n): readonly string[] {\n const values = new Set<string>();\n const checker = checkerFor(context);\n collectTexts(baseTypeAtNode(context, node));\n collectTexts(symbolTypeAtNode(context, node));\n return [...values];\n\n function collectTexts(type: TsgoType | undefined): void {\n if (!type) {\n return;\n }\n const texts = Array.isArray(type.texts) ? type.texts : [];\n for (const text of [...texts, checker.typeToString(type)]) {\n if (text) {\n values.add(text);\n }\n }\n }\n}\n\nexport function classifyTypeText(\n text: string | undefined,\n): \"any\" | \"bigint\" | \"boolean\" | \"nullish\" | \"number\" | \"regexp\" | \"string\" | \"unknown\" | \"other\" {\n return classifyTypeTextFromRust(text);\n}\n\nexport function splitTopLevelTypeText(text: string, delimiter: \"|\" | \"&\" | \",\"): readonly string[] {\n return splitTopLevelTypeTextFromRust(text, delimiter);\n}\n\nexport function splitTypeText(text: string): readonly string[] {\n return splitTypeTextFromRust(text);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","names":["#snapshot","#client","#files","#config","#lastRefreshMs","#projects"],"sources":["../ts/session.ts"],"sourcesContent":["import { statSync } from \"node:fs\";\n\nimport { type ProjectResponse, TsgoApiClient } from \"@corsa-bind/napi\";\n\nimport type { TsgoSignature, TsgoSymbol, TsgoType, TsgoTypePredicate } from \"./types\";\nimport type { ResolvedProjectConfig, ResolvedRuntimeOptions } from \"./types\";\n\ntype FileCache = {\n mtimeMs: number;\n projectId: string;\n typeByPosition: Map<number, TsgoType | undefined>;\n symbolByPosition: Map<number, TsgoSymbol | undefined>;\n};\n\nexport class TsgoProjectSession {\n #client?: TsgoApiClient;\n #config?: { options: unknown; fileNames: string[] };\n #snapshot?: string;\n #projects: ProjectResponse[] = [];\n #files = new Map<string, FileCache>();\n #lastRefreshMs = 0;\n\n constructor(\n readonly project: ResolvedProjectConfig,\n readonly runtime: ResolvedRuntimeOptions,\n ) {}\n\n close(): void {\n if (this.#snapshot) {\n this.#client?.releaseHandle(this.#snapshot);\n this.#snapshot = undefined;\n }\n this.#client?.close();\n this.#client = undefined;\n this.#files.clear();\n }\n\n getCompilerOptions(): unknown {\n return this.config().options;\n }\n\n getRootFileNames(): readonly string[] {\n return this.config().fileNames;\n }\n\n getTypeAtPosition(fileName: string, position: number): TsgoType | undefined {\n const state = this.fileState(fileName);\n if (!state.typeByPosition.has(position)) {\n state.typeByPosition.set(\n position,\n this.client().getTypeAtPosition(this.#snapshot!, state.projectId, fileName, position) as\n | TsgoType\n | undefined,\n );\n }\n return state.typeByPosition.get(position);\n }\n\n getSymbolAtPosition(fileName: string, position: number): TsgoSymbol | undefined {\n const state = this.fileState(fileName);\n if (!state.symbolByPosition.has(position)) {\n state.symbolByPosition.set(\n position,\n this.client().getSymbolAtPosition(this.#snapshot!, state.projectId, fileName, position) as\n | TsgoSymbol\n | undefined,\n );\n }\n return state.symbolByPosition.get(position);\n }\n\n getTypeOfSymbol(symbol: TsgoSymbol): TsgoType | undefined {\n return this.client().getTypeOfSymbol(this.#snapshot!, this.projectId(), symbol.id) as\n | TsgoType\n | undefined;\n }\n\n getDeclaredTypeOfSymbol(symbol: TsgoSymbol): TsgoType | undefined {\n return this.client().getDeclaredTypeOfSymbol(this.#snapshot!, this.projectId(), symbol.id) as\n | TsgoType\n | undefined;\n }\n\n typeToString(type: TsgoType, flags?: number): string {\n return this.client().typeToString(this.#snapshot!, this.projectId(), type.id, undefined, flags);\n }\n\n getBaseTypeOfLiteralType(type: TsgoType): TsgoType | undefined {\n return this.client().callJson(\"getBaseTypeOfLiteralType\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n });\n }\n\n getPropertiesOfType(type: TsgoType): readonly TsgoSymbol[] {\n return (\n this.client().callJson(\"getPropertiesOfType\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n }) ?? []\n );\n }\n\n getSignaturesOfType(type: TsgoType, kind: number): readonly TsgoSignature[] {\n return this.client().callJson(\"getSignaturesOfType\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n kind,\n });\n }\n\n getReturnTypeOfSignature(signature: TsgoSignature): TsgoType | undefined {\n return this.client().callJson(\"getReturnTypeOfSignature\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n signature: signature.id,\n });\n }\n\n getTypePredicateOfSignature(signature: TsgoSignature): TsgoTypePredicate | undefined {\n return this.client().callJson(\"getTypePredicateOfSignature\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n signature: signature.id,\n });\n }\n\n getBaseTypes(type: TsgoType): readonly TsgoType[] {\n return (\n this.client().callJson(\"getBaseTypes\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n }) ?? []\n );\n }\n\n getTypeArguments(type: TsgoType): readonly TsgoType[] {\n return this.client().getTypeArguments(\n this.#snapshot!,\n this.projectId(),\n type.id,\n type.objectFlags,\n ) as unknown as readonly TsgoType[];\n }\n\n private client(): TsgoApiClient {\n if (!this.#client) {\n this.#client = TsgoApiClient.spawn({\n executable: this.runtime.executable,\n cwd: this.runtime.cwd,\n mode: this.runtime.mode,\n });\n this.#client.initialize();\n }\n return this.#client;\n }\n\n private config(): { options: unknown; fileNames: string[] } {\n if (!this.#config) {\n this.#config = this.client().parseConfigFile(this.project.configPath);\n }\n const config = this.#config;\n if (!config) {\n throw new Error(`corsa-oxlint could not parse a tsgo config for ${this.project.configPath}`);\n }\n return config;\n }\n\n private fileState(fileName: string): FileCache {\n this.refreshIfNeeded(fileName);\n const current = this.#files.get(fileName);\n if (current) {\n return current;\n }\n const project = this.client().callJson<ProjectResponse | null>(\"getDefaultProjectForFile\", {\n snapshot: this.#snapshot,\n file: fileName,\n });\n const state: FileCache = {\n mtimeMs: statMtimeMs(fileName),\n projectId: project?.id ?? this.projectId(),\n typeByPosition: new Map(),\n symbolByPosition: new Map(),\n };\n this.#files.set(fileName, state);\n return state;\n }\n\n private refreshIfNeeded(fileName: string): void {\n const now = Date.now();\n const expired = now - this.#lastRefreshMs > this.runtime.cacheLifetimeMs;\n const stale =\n !this.#snapshot || statMtimeMs(fileName) !== this.#files.get(fileName)?.mtimeMs || expired;\n if (!stale) {\n return;\n }\n const previous = this.#snapshot;\n const response = this.client().updateSnapshot(\n previous\n ? { fileChanges: { changed: [fileName] } }\n : { openProject: this.project.configPath },\n );\n this.#snapshot = response.snapshot;\n this.#projects = response.projects;\n this.#lastRefreshMs = now;\n this.#files.clear();\n if (previous && previous !== this.#snapshot) {\n this.client().releaseHandle(previous);\n }\n }\n\n private projectId(): string {\n const id = this.#projects[0]?.id;\n if (!id) {\n throw new Error(`corsa-oxlint could not resolve a tsgo project for ${this.project.filename}`);\n }\n return id;\n }\n}\n\nfunction statMtimeMs(fileName: string): number {\n try {\n return statSync(fileName).mtimeMs;\n } catch {\n return 0;\n }\n}\n"],"mappings":";;;AAcA,IAAa,qBAAb,MAAgC;CAC9B;CACA;CACA;CACA,YAA+B,EAAE;CACjC,yBAAS,IAAI,KAAwB;CACrC,iBAAiB;CAEjB,YACE,SACA,SACA;AAFS,OAAA,UAAA;AACA,OAAA,UAAA;;CAGX,QAAc;AACZ,MAAI,MAAA,UAAgB;AAClB,SAAA,QAAc,cAAc,MAAA,SAAe;AAC3C,SAAA,WAAiB,KAAA;;AAEnB,QAAA,QAAc,OAAO;AACrB,QAAA,SAAe,KAAA;AACf,QAAA,MAAY,OAAO;;CAGrB,qBAA8B;AAC5B,SAAO,KAAK,QAAQ,CAAC;;CAGvB,mBAAsC;AACpC,SAAO,KAAK,QAAQ,CAAC;;CAGvB,kBAAkB,UAAkB,UAAwC;EAC1E,MAAM,QAAQ,KAAK,UAAU,SAAS;AACtC,MAAI,CAAC,MAAM,eAAe,IAAI,SAAS,CACrC,OAAM,eAAe,IACnB,UACA,KAAK,QAAQ,CAAC,kBAAkB,MAAA,UAAiB,MAAM,WAAW,UAAU,SAAS,CAGtF;AAEH,SAAO,MAAM,eAAe,IAAI,SAAS;;CAG3C,oBAAoB,UAAkB,UAA0C;EAC9E,MAAM,QAAQ,KAAK,UAAU,SAAS;AACtC,MAAI,CAAC,MAAM,iBAAiB,IAAI,SAAS,CACvC,OAAM,iBAAiB,IACrB,UACA,KAAK,QAAQ,CAAC,oBAAoB,MAAA,UAAiB,MAAM,WAAW,UAAU,SAAS,CAGxF;AAEH,SAAO,MAAM,iBAAiB,IAAI,SAAS;;CAG7C,gBAAgB,QAA0C;AACxD,SAAO,KAAK,QAAQ,CAAC,gBAAgB,MAAA,UAAiB,KAAK,WAAW,EAAE,OAAO,GAAG;;CAKpF,wBAAwB,QAA0C;AAChE,SAAO,KAAK,QAAQ,CAAC,wBAAwB,MAAA,UAAiB,KAAK,WAAW,EAAE,OAAO,GAAG;;CAK5F,aAAa,MAAgB,OAAwB;AACnD,SAAO,KAAK,QAAQ,CAAC,aAAa,MAAA,UAAiB,KAAK,WAAW,EAAE,KAAK,IAAI,KAAA,GAAW,MAAM;;CAGjG,yBAAyB,MAAsC;AAC7D,SAAO,KAAK,QAAQ,CAAC,SAAS,4BAA4B;GACxD,UAAU,MAAA;GACV,SAAS,KAAK,WAAW;GACzB,MAAM,KAAK;GACZ,CAAC;;CAGJ,oBAAoB,MAAuC;AACzD,SACE,KAAK,QAAQ,CAAC,SAAS,uBAAuB;GAC5C,UAAU,MAAA;GACV,SAAS,KAAK,WAAW;GACzB,MAAM,KAAK;GACZ,CAAC,IAAI,EAAE;;CAIZ,oBAAoB,MAAgB,MAAwC;AAC1E,SAAO,KAAK,QAAQ,CAAC,SAAS,uBAAuB;GACnD,UAAU,MAAA;GACV,SAAS,KAAK,WAAW;GACzB,MAAM,KAAK;GACX;GACD,CAAC;;CAGJ,yBAAyB,WAAgD;AACvE,SAAO,KAAK,QAAQ,CAAC,SAAS,4BAA4B;GACxD,UAAU,MAAA;GACV,SAAS,KAAK,WAAW;GACzB,WAAW,UAAU;GACtB,CAAC;;CAGJ,4BAA4B,WAAyD;AACnF,SAAO,KAAK,QAAQ,CAAC,SAAS,+BAA+B;GAC3D,UAAU,MAAA;GACV,SAAS,KAAK,WAAW;GACzB,WAAW,UAAU;GACtB,CAAC;;CAGJ,aAAa,MAAqC;AAChD,SACE,KAAK,QAAQ,CAAC,SAAS,gBAAgB;GACrC,UAAU,MAAA;GACV,SAAS,KAAK,WAAW;GACzB,MAAM,KAAK;GACZ,CAAC,IAAI,EAAE;;CAIZ,iBAAiB,MAAqC;AACpD,SAAO,KAAK,QAAQ,CAAC,iBACnB,MAAA,UACA,KAAK,WAAW,EAChB,KAAK,IACL,KAAK,YACN;;CAGH,SAAgC;AAC9B,MAAI,CAAC,MAAA,QAAc;AACjB,SAAA,SAAe,cAAc,MAAM;IACjC,YAAY,KAAK,QAAQ;IACzB,KAAK,KAAK,QAAQ;IAClB,MAAM,KAAK,QAAQ;IACpB,CAAC;AACF,SAAA,OAAa,YAAY;;AAE3B,SAAO,MAAA;;CAGT,SAA4D;AAC1D,MAAI,CAAC,MAAA,OACH,OAAA,SAAe,KAAK,QAAQ,CAAC,gBAAgB,KAAK,QAAQ,WAAW;EAEvE,MAAM,SAAS,MAAA;AACf,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,kDAAkD,KAAK,QAAQ,aAAa;AAE9F,SAAO;;CAGT,UAAkB,UAA6B;AAC7C,OAAK,gBAAgB,SAAS;EAC9B,MAAM,UAAU,MAAA,MAAY,IAAI,SAAS;AACzC,MAAI,QACF,QAAO;EAET,MAAM,UAAU,KAAK,QAAQ,CAAC,SAAiC,4BAA4B;GACzF,UAAU,MAAA;GACV,MAAM;GACP,CAAC;EACF,MAAM,QAAmB;GACvB,SAAS,YAAY,SAAS;GAC9B,WAAW,SAAS,MAAM,KAAK,WAAW;GAC1C,gCAAgB,IAAI,KAAK;GACzB,kCAAkB,IAAI,KAAK;GAC5B;AACD,QAAA,MAAY,IAAI,UAAU,MAAM;AAChC,SAAO;;CAGT,gBAAwB,UAAwB;EAC9C,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,UAAU,MAAM,MAAA,gBAAsB,KAAK,QAAQ;AAGzD,MAAI,EADF,CAAC,MAAA,YAAkB,YAAY,SAAS,KAAK,MAAA,MAAY,IAAI,SAAS,EAAE,WAAW,SAEnF;EAEF,MAAM,WAAW,MAAA;EACjB,MAAM,WAAW,KAAK,QAAQ,CAAC,eAC7B,WACI,EAAE,aAAa,EAAE,SAAS,CAAC,SAAS,EAAE,EAAE,GACxC,EAAE,aAAa,KAAK,QAAQ,YAAY,CAC7C;AACD,QAAA,WAAiB,SAAS;AAC1B,QAAA,WAAiB,SAAS;AAC1B,QAAA,gBAAsB;AACtB,QAAA,MAAY,OAAO;AACnB,MAAI,YAAY,aAAa,MAAA,SAC3B,MAAK,QAAQ,CAAC,cAAc,SAAS;;CAIzC,YAA4B;EAC1B,MAAM,KAAK,MAAA,SAAe,IAAI;AAC9B,MAAI,CAAC,GACH,OAAM,IAAI,MAAM,qDAAqD,KAAK,QAAQ,WAAW;AAE/F,SAAO;;;AAIX,SAAS,YAAY,UAA0B;AAC7C,KAAI;AACF,SAAO,SAAS,SAAS,CAAC;SACpB;AACN,SAAO"}
1
+ {"version":3,"file":"session.js","names":["#snapshot","#client","#files","#config","#lastRefreshMs","#projects"],"sources":["../ts/session.ts"],"sourcesContent":["import { statSync } from \"node:fs\";\n\nimport { type ProjectResponse, TsgoApiClient } from \"@corsa-bind/napi\";\n\nimport type { TsgoSignature, TsgoSymbol, TsgoType, TsgoTypePredicate } from \"./types\";\nimport type { ResolvedProjectConfig, ResolvedRuntimeOptions } from \"./types\";\n\ntype FileCache = {\n mtimeMs: number;\n projectId: string;\n typeByPosition: Map<number, TsgoType | undefined>;\n symbolByPosition: Map<number, TsgoSymbol | undefined>;\n};\n\nexport class TsgoProjectSession {\n #client?: TsgoApiClient;\n #config?: { options: unknown; fileNames: string[] };\n #snapshot?: string;\n #projects: ProjectResponse[] = [];\n #files = new Map<string, FileCache>();\n #lastRefreshMs = 0;\n\n constructor(\n readonly project: ResolvedProjectConfig,\n readonly runtime: ResolvedRuntimeOptions,\n ) {}\n\n close(): void {\n if (this.#snapshot) {\n this.#client?.releaseHandle(this.#snapshot);\n this.#snapshot = undefined;\n }\n this.#client?.close();\n this.#client = undefined;\n this.#files.clear();\n }\n\n getCompilerOptions(): unknown {\n return this.config().options;\n }\n\n getRootFileNames(): readonly string[] {\n return this.config().fileNames;\n }\n\n getTypeAtPosition(fileName: string, position: number): TsgoType | undefined {\n const state = this.fileState(fileName);\n if (!state.typeByPosition.has(position)) {\n state.typeByPosition.set(\n position,\n this.client().getTypeAtPosition(this.#snapshot!, state.projectId, fileName, position) as\n | TsgoType\n | undefined,\n );\n }\n return state.typeByPosition.get(position);\n }\n\n getSymbolAtPosition(fileName: string, position: number): TsgoSymbol | undefined {\n const state = this.fileState(fileName);\n if (!state.symbolByPosition.has(position)) {\n state.symbolByPosition.set(\n position,\n this.client().getSymbolAtPosition(this.#snapshot!, state.projectId, fileName, position) as\n | TsgoSymbol\n | undefined,\n );\n }\n return state.symbolByPosition.get(position);\n }\n\n getTypeOfSymbol(symbol: TsgoSymbol): TsgoType | undefined {\n return this.client().getTypeOfSymbol(this.#snapshot!, this.projectId(), symbol.id) as\n | TsgoType\n | undefined;\n }\n\n getDeclaredTypeOfSymbol(symbol: TsgoSymbol): TsgoType | undefined {\n return this.client().getDeclaredTypeOfSymbol(this.#snapshot!, this.projectId(), symbol.id) as\n | TsgoType\n | undefined;\n }\n\n typeToString(type: TsgoType, flags?: number): string {\n return this.client().typeToString(this.#snapshot!, this.projectId(), type.id, undefined, flags);\n }\n\n getBaseTypeOfLiteralType(type: TsgoType): TsgoType | undefined {\n return this.client().callJson(\"getBaseTypeOfLiteralType\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n });\n }\n\n getPropertiesOfType(type: TsgoType): readonly TsgoSymbol[] {\n return (\n this.client().callJson(\"getPropertiesOfType\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n }) ?? []\n );\n }\n\n getSignaturesOfType(type: TsgoType, kind: number): readonly TsgoSignature[] {\n return this.client().callJson(\"getSignaturesOfType\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n kind,\n });\n }\n\n getReturnTypeOfSignature(signature: TsgoSignature): TsgoType | undefined {\n return this.client().callJson(\"getReturnTypeOfSignature\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n signature: signature.id,\n });\n }\n\n getTypePredicateOfSignature(signature: TsgoSignature): TsgoTypePredicate | undefined {\n return this.client().callJson(\"getTypePredicateOfSignature\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n signature: signature.id,\n });\n }\n\n getBaseTypes(type: TsgoType): readonly TsgoType[] {\n return (\n this.client().callJson(\"getBaseTypes\", {\n snapshot: this.#snapshot,\n project: this.projectId(),\n type: type.id,\n }) ?? []\n );\n }\n\n getTypeArguments(type: TsgoType): readonly TsgoType[] {\n return this.client().getTypeArguments(\n this.#snapshot!,\n this.projectId(),\n type.id,\n type.objectFlags,\n ) as unknown as readonly TsgoType[];\n }\n\n private client(): TsgoApiClient {\n if (!this.#client) {\n this.#client = TsgoApiClient.spawn({\n executable: this.runtime.executable,\n cwd: this.runtime.cwd,\n mode: this.runtime.mode,\n });\n this.#client.initialize();\n }\n return this.#client;\n }\n\n private config(): { options: unknown; fileNames: string[] } {\n if (!this.#config) {\n this.#config = this.client().parseConfigFile(this.project.configPath);\n }\n const config = this.#config;\n if (!config) {\n throw new Error(`corsa-oxlint could not parse a tsgo config for ${this.project.configPath}`);\n }\n return config;\n }\n\n private fileState(fileName: string): FileCache {\n this.refreshIfNeeded(fileName);\n const current = this.#files.get(fileName);\n if (current) {\n return current;\n }\n const project = this.client().callJson<ProjectResponse | null>(\"getDefaultProjectForFile\", {\n snapshot: this.#snapshot,\n file: fileName,\n });\n const state: FileCache = {\n mtimeMs: statMtimeMs(fileName),\n projectId: project?.id ?? this.projectId(),\n typeByPosition: new Map(),\n symbolByPosition: new Map(),\n };\n this.#files.set(fileName, state);\n return state;\n }\n\n private refreshIfNeeded(fileName: string): void {\n const now = Date.now();\n const expired = now - this.#lastRefreshMs > this.runtime.cacheLifetimeMs;\n const stale =\n !this.#snapshot || statMtimeMs(fileName) !== this.#files.get(fileName)?.mtimeMs || expired;\n if (!stale) {\n return;\n }\n const previous = this.#snapshot;\n const response = this.client().updateSnapshot(\n previous\n ? { fileChanges: { changed: [fileName] } }\n : { openProject: this.project.configPath },\n );\n this.#snapshot = response.snapshot;\n this.#projects = response.projects;\n this.#lastRefreshMs = now;\n this.#files.clear();\n if (previous && previous !== this.#snapshot) {\n this.client().releaseHandle(previous);\n }\n }\n\n private projectId(): string {\n const id = this.#projects[0]?.id;\n if (!id) {\n throw new Error(`corsa-oxlint could not resolve a tsgo project for ${this.project.filename}`);\n }\n return id;\n }\n}\n\nfunction statMtimeMs(fileName: string): number {\n try {\n return statSync(fileName).mtimeMs;\n } catch {\n return 0;\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "corsa-oxlint",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Type-aware Oxlint helpers powered by corsa and typescript-go",
5
5
  "homepage": "https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint",
6
6
  "bugs": {
@@ -59,9 +59,9 @@
59
59
  "./package.json": "./package.json"
60
60
  },
61
61
  "dependencies": {
62
- "@oxlint/plugins": "1.57.0",
63
- "oxlint": "1.57.0",
64
- "@corsa-bind/napi": "0.7.1"
62
+ "@oxlint/plugins": "1.65.0",
63
+ "oxlint": "1.65.0",
64
+ "@corsa-bind/napi": "0.8.0"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">=22"