eslint-plugin-sonarjs
Version:
48 lines (47 loc) • 2.53 kB
TypeScript
import type { TSESTree } from '@typescript-eslint/utils';
import type { RequiredParserServices } from './parser-services.js';
export type TypeOrigin = {
internal: TSESTree.TypeNode[];
external: TSESTree.TypeNode[];
};
/**
* Partitions the syntactic members of a type annotation into "internal"
* (user-writable in this project) and "external" (declared in node_modules
* or in the TypeScript default lib).
*
* Operates on the syntactic AST node, not on a resolved `ts.Type`. Returning
* the original AST nodes lets callers produce locations, suggestions, or
* fixes targeting exactly what the user wrote.
*
* Classification rules per top-level member:
* - Keyword / literal types -> internal (the user wrote them directly).
* - TSTypeReference -> resolves the type name to a symbol and inspects its
* declarations.
* - TSIndexedAccessType with a literal property name -> resolves the accessed
* property and inspects its declarations. When no named property matches,
* the access goes through an index signature and the signature's own
* declaration is used instead (falling back to the declaration of the
* indexed type itself for signatures the checker synthesizes, such as
* `Record<K, V>`).
* - Any other composite constructor (TSIntersectionType, TSArrayType,
* TSTypeLiteral, TSConditionalType, ...) -> internal at the top level. We
* do not recurse; callers can if they need to.
*
* A member is external only when ALL of the declarations found for it live in
* files that satisfy `isSourceFileFromExternalLibrary` or
* `isSourceFileDefaultLibrary`. Any local declaration (declaration-merging
* escape hatch) makes the member internal, and so does a member whose
* declarations cannot be resolved at all — being reportable is the safe
* default, since callers use this to decide whether a fix is applicable.
*
* Known limitations:
* - Alias chains are not followed. If the user re-aliases an external type
* locally (e.g. `type Inner = ReactNode`), the local alias is internal
* because the user has a place to edit.
* - An indexed access with a non-literal index (`Ext[Key]`) is internal: the
* property cannot be pinned down syntactically.
* - A property inherited from an external base is external even though the
* local type could redeclare it, because the declaration the user would
* have to change is the external one.
*/
export declare function classifyTypesByOrigin(typeNode: TSESTree.TypeNode, services: RequiredParserServices): TypeOrigin;