@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
166 lines (165 loc) • 8.42 kB
TypeScript
import type { PathLike } from 'fs';
import type { RParseRequest } from '../../r-bridge/retriever';
import type { InvalidationEventHandler } from '../cache/flowr-cache';
/**
* Just a readable alias for file paths, mostly for documentation purposes.
* We separate {@link PathLike} types from string paths that are used for project paths.
*/
export type FilePath = string;
/**
* Some files have a special meaning in R projects, e.g., the `DESCRIPTION` file in R packages.
* This list may be extended in the future and reflects files that the {@link FlowrAnalyzer} can do something interesting with.
* If you add an interesting file that is only part of your plugin infrastructure, please use the `other` role.
*/
export declare enum FileRole {
/** The `DESCRIPTION` file in R packages, this is the only currently supported special file. */
Description = "description",
/** The `NAMESPACE` file in R packages, currently not specially supported. */
Namespace = "namespace",
/** The `NEWS` file in R packages */
News = "news",
/** Vignette files, e.g., R Markdown files in the `vignettes/` folder */
Vignette = "vignette",
/** Test source files, e.g., files in the `tests/` folder */
Test = "test",
/**
* Files below an `inst/` folder, which R installs verbatim into the package root (resources/scripts, e.g., `inst/REFERENCES.R`, `inst/CITATION`, `inst/extdata/...`).
* These are not part of the package namespace source, so tooling may want to treat them separately.
*/
Install = "install",
/** Data files, e.g., `R/sysdata.rda`, currently not specially supported. */
Data = "data",
/** Signals separate license files, but please note, that DESCRIPTION files may contain license info too */
License = "license",
/** Files describing a project's virtual/pinned package environment, e.g., `renv.lock`, `rv.lock` or `uvr.lock`. */
VirtualEnv = "virtual-env",
/** A project manifest that is no `DESCRIPTION`, e.g. the `rproject.toml` of an rv project or the `uvr.toml` of a uvr project. */
Manifest = "manifest",
/**
* R sources evaluated at startup, before any project code (`.Rprofile`, `Rprofile.site`).
* These commonly bootstrap a package manager, e.g. by sourcing `packrat/init.R` or `renv/activate.R`.
*/
Startup = "startup",
/**
* Environment-variable definitions read at startup (`.Renviron`, `Renviron.site`). These are `KEY=value`
* files, not R source, so they are labeled but not parsed as R.
*/
Environment = "environment",
/**
* Catch-all for any file that provides usable R source code to incorporate into the analysis.
* Please note, that the loading order/inclusion and even potential relevance of these source files
* is determined by the loading order plugins (cf. {@link PluginType.LoadingOrder})
* in the {@link FlowrAnalyzerLoadingOrderContext}.
*/
Source = "source",
/** Other special files that are not specifically supported by flowR but may be interesting for some analyses. */
Other = "other"
}
export type StringableContent = {
toString(): string;
};
/**
* This is the basic interface for all files known to the FlowrAnalyzer.
* You can implement this interface to provide custom file loading mechanisms.
* Mostly, we will be interested in text files (or decorations thereof).
* If you want to load other file types, you either have to transform them into a presentation supported by flowR
* or add your own file loader plugin (similar to the {@link FlowrAnalyzerDescriptionFilePlugin}).
*
* See {@link FlowrFile} for a basic single-cache implementation and {@link FlowrTextFile} for a text-file specific implementation.
* If you want to pass in inline text files, see {@link FlowrInlineTextFile}.
* @typeParam Content - The type of the content returned by the `content()` method.
*/
export interface FlowrFileProvider<Content extends {
toString(): string;
} = {
toString(): string;
}> {
/**
* The role(s) of this file, if any, in general your file should _not_ decide for itself what role it has in the project context,
* this is for the loaders plugins to decide (cf. {@link PluginType}) as they can, e.g., respect ignore files, updated mappings, etc.
* However, they will 1) set this role as soon as they decide on it (using {@link assignRole}) and 2) try to respect an already assigned role (however, user configurations may override this).
*/
roles?: readonly FileRole[];
/**
* The path to the file, this is used for identification and logging purposes.
* If the file does not exist on disk, this can be a virtual path (e.g. for inline files).
* Even though this is a getter, please make sure that the operation is cheap and deterministic (some decorators may overwrite the path, e.g., because they support other protocols).
*/
path(): string;
/**
* The content of the file, this may be cached by the implementation and does not have to be expensive.
* You can used stream based implementations but right now there is no external, project-wide expressions of life cycles for files.
* So make sure your implementation closes the resource as soon as possible.
*/
content(): Content;
/**
* Assign a role to this file, this should be done by the loader plugins (cf. {@link PluginType}).
* **Do not call this method yourself unless you are a file-loader plugin and/or really know what you are doing, this may break plugin assumptions!**
*/
assignRole(role: FileRole): void;
/**
* Set the appropriate callback to trigger updates in case of an 'invalidate'
*/
addOnInvalidate(callback: InvalidationEventHandler<Content>): void;
/**
* Remove a previously added callback
*/
removeOnInvalidate(callback: InvalidationEventHandler<Content>): void;
/**
* Reload the file content because something has changed.
*/
invalidate(): void;
}
/**
* A basic implementation of the {@link FlowrFileProvider} interface that caches the content after the first load (i.e., updates on disk are ignored).
*
* See {@link FlowrTextFile} for a text-file specific implementation and {@link FlowrInlineTextFile} for inline text files.
*/
export declare abstract class FlowrFile<Content extends StringableContent = StringableContent> implements FlowrFileProvider<Content> {
private contentCache;
protected filePath: PathLike;
private _roles?;
private onInvalidate;
static readonly INLINE_PATH = "@inline";
constructor(filePath: PathLike, roles?: readonly FileRole[]);
get roles(): readonly FileRole[] | undefined;
path(): string;
content(): Content;
/**
* Allows to overwrite the content cache.
* @protected
*/
protected setContent(content: Content): void;
protected abstract loadContent(): Content;
assignRole(role: FileRole): void;
/**
* Creates a {@link FlowrFile} from a given {@link RParseRequest}.
* @see {@link FlowrTextFile}
* @see {@link FlowrInlineTextFile}
*/
static fromRequest(request: RParseRequest): FlowrFile<string>;
addOnInvalidate(callback: InvalidationEventHandler<Content>): void;
removeOnInvalidate(callback: InvalidationEventHandler<Content>): void;
invalidate(): void;
}
/**
* A basic implementation of the {@link FlowrFileProvider} interface for text files that caches the content after the first load (i.e., updates on disk are ignored).
*/
export declare class FlowrTextFile extends FlowrFile<string> {
protected loadContent(): string;
}
/**
* A basic implementation of the {@link FlowrFileProvider} interface for (constant) inline text files.
* This is also useful for "special" files like the `DESCRIPTION` file in R packages that you want to pass in directly.
* These will be handled by the {@link FlowrAnalyzerDescriptionFilePlugin} (e.g., by using the {@link FlowrDescriptionFile#from} method decorator).
*/
export declare class FlowrInlineTextFile extends FlowrFile<string> {
private contentStr;
constructor(path: PathLike, content: string);
protected loadContent(): string;
/**
* Update the content of this inline file and invalidate the cache to trigger updates in the analysis.
* @see {@link FlowrFile#invalidate}
*/
updateInlineContent(newContent: string): void;
}