UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

206 lines (205 loc) 9.17 kB
import type { FlowrSearchLike } from '../search/flowr-search-builder'; import type { FlowrSearchElement, FlowrSearchElements } from '../search/flowr-search'; import type { MergeableRecord } from '../util/objects'; import type { GeneratorNames } from '../search/search-executor/search-generators'; import type { TransformerNames } from '../search/search-executor/search-transformer'; import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate'; import type { LintingRuleConfig, LintingRuleMetadata, LintingRuleNames, LintingRuleResult } from './linter-rules'; import type { AsyncOrSync, DeepPartial, DeepReadonly } from 'ts-essentials'; import type { LintingRuleTag } from './linter-tags'; import type { SourceLocation } from '../util/range'; import type { DataflowInformation } from '../dataflow/info'; import type { ControlFlowInformation } from '../control-flow/control-flow-graph'; import type { ReadonlyFlowrAnalysisProvider } from '../project/flowr-analyzer'; import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id'; export interface LinterRuleInformation<Config extends MergeableRecord = never> { /** Human-Readable name of the linting rule. */ readonly name: string; /** * The default config for this linting rule. * This config is combined with the user config when executing the rule. */ readonly defaultConfig: NoInfer<DeepReadonly<Config>>; /** * A short list of tags that describe and categorize the linting rule. */ readonly tags: readonly LintingRuleTag[]; /** * The linting rule's certainty in terms of the rule's calculations' precision and recall. */ readonly certainty: LintingRuleCertainty; /** * A short description of the linting rule. * This is used to display the rule in the UI and to provide a brief overview of what the rule does. */ readonly description: string; } /** * The base interface for a linting rule, which contains all of its relevant settings. * The registry of valid linting rules is stored in {@link LintingRules}. */ export interface LintingRule<Result extends LintingResult, Metadata extends MergeableRecord, Config extends MergeableRecord = never, Info = ParentInformation, Elements extends FlowrSearchElement<Info>[] = FlowrSearchElement<Info>[]> { /** * Creates a flowR search that will then be executed and whose results will be passed to {@link processSearchResult}. * In the future, additional optimizations and transformations may be applied to the search between this function and {@link processSearchResult}. */ readonly createSearch: (config: Config) => FlowrSearchLike<Info, GeneratorNames, TransformerNames[], FlowrSearchElements<Info, Elements>>; /** * Processes the search results of the search created through {@link createSearch}. * This function is expected to return the linting results from this rule for the given search, ie usually the given script file. */ readonly processSearchResult: (elements: FlowrSearchElements<Info, Elements>, config: Config, data: { normalize: NormalizedAst; dataflow: DataflowInformation; cfg: ControlFlowInformation; analyzer: ReadonlyFlowrAnalysisProvider; }) => AsyncOrSync<{ results: Result[]; '.meta': Metadata; }>; /** * A set of functions used to pretty-print the given linting result. * By default, the {@link LintingResult#certainty} and whether any {@link LintingResult#quickFix} values are available is automatically printed alongside this information. */ readonly prettyPrint: { [C in LintingPrettyPrintContext]: (result: Result, metadata: Metadata) => string; }; readonly info: LinterRuleInformation<NoInfer<Config>>; } interface BaseQuickFix { /** * The type of the quick fix. */ readonly type: string; /** * A short, human-readable description of the quick fix. */ readonly description: string; /** * The range of the text that should be replaced. */ readonly loc: SourceLocation; } export interface LintQuickFixReplacement extends BaseQuickFix { readonly type: 'replace'; /** * The text that should replace the given range. */ readonly replacement: string; } export interface LintQuickFixRemove extends BaseQuickFix { readonly type: 'remove'; } export type LintQuickFix = LintQuickFixReplacement | LintQuickFixRemove; /** * A linting result for a single linting rule match. */ export interface LintingResult { /** The certainty of the linting result. */ readonly certainty: LintingResultCertainty; /** * If available, what to do to fix the linting result. */ readonly quickFix?: LintQuickFix[]; /** * The node ID or IDs involved in this linting result, if applicable. */ readonly involvedId: NodeId | NodeId[] | undefined; } export interface ConfiguredLintingRule<Name extends LintingRuleNames = LintingRuleNames> { readonly name: Name; readonly config: DeepPartial<LintingRuleConfig<Name>>; } /** * For when a linting rule throws an error during execution */ export interface LintingResultsError { /** the error thrown */ readonly error: unknown; } export interface LintingResultsSuccess<Name extends LintingRuleNames> { results: LintingRuleResult<Name>[]; '.meta': LintingRuleMetadata<Name> & { readonly searchTimeMs: number; readonly processTimeMs: number; }; } /** * The results of executing a linting rule. * @see {@link LintingResults.isError} and {@link LintingResults.isSuccess} to differentiate between success and error results. */ export type LintingResults<Name extends LintingRuleNames> = LintingResultsSuccess<Name> | LintingResultsError; /** * Helper functions for working with {@link LintingResults}. */ export declare const LintingResults: { /** * Checks whether the given linting results represent an error. * @see {@link LintingResultsError} * @see {@link LintingResults.isSuccess} */ readonly isError: <Name extends LintingRuleNames>(this: void, o: LintingResults<Name>) => o is LintingResultsError; /** * Checks whether the given linting results represent a successful execution. * @see {@link LintingResultsSuccess} * @see {@link LintingResults.isError} * @see {@link LintingResults.unpackSuccess} */ readonly isSuccess: <Name extends LintingRuleNames>(this: void, o: LintingResults<Name>) => o is LintingResultsSuccess<Name>; /** * Unpacks the given linting results, throwing an error if they represent an error. */ readonly unpackSuccess: <Name extends LintingRuleNames>(this: void, o: LintingResults<Name>) => LintingResultsSuccess<Name>; /** * Gets all involved node IDs from the given linting results. * If the results represent an error, an empty set is returned. */ readonly allInvolvedIds: <L extends LintingRuleNames>(this: void, res: LintingResults<L> | undefined) => Set<NodeId>; /** * Gets all locations from the given linting results, i.e. the `loc` property of all results that have a location. */ readonly allLocations: <L extends LintingRuleNames>(this: void, res: LintingResults<L> | undefined) => SourceLocation[]; /** * Stringifies the error contained in the given linting results error. */ readonly stringifyError: (this: void, { error }: LintingResultsError) => string; /** * Checks whether the given linting result has a location, i.e. whether it has a `loc` property. */ readonly hasLocation: <R extends LintingResult>(this: void, res: R) => res is R & { loc: SourceLocation; }; }; export declare enum LintingResultCertainty { /** * The linting rule cannot say for sure whether the result is correct or not. * This linting certainty should be used for linting results whose calculations are based on estimations involving unknown side effects, reflection, etc. */ Uncertain = "uncertain", /** * The linting rule is certain that the reported lint is real. * This linting certainty should be used for linting results whose calculations do not involve estimates or other unknown factors. */ Certain = "certain" } export declare enum LintingRuleCertainty { /** * Linting rules that are expected to have both high precision and high recall. */ Exact = "exact", /** * Linting rules that are expected to have high precision, but not necessarily high recall. * Rules with this certainty generally ensure that the results they return are correct, but may not return all results. */ BestEffort = "best-effort", /** * Linting rules that are expected to have high recall, but not necessarily high precision. * Rules with this certainty generally return all relevant results, but may also include some incorrect matches. */ OverApproximative = "over-approximative" } export declare enum LintingPrettyPrintContext { Query = "query", Full = "full" } export {};