import { CharStream, Token } from "antlr4ng"; import { ICompiledST, ICompilerParameters, IST, ISTGroup } from "./compiler/common.js"; import { AttributeRenderer } from "./AttributeRenderer.js"; import { FormalArgument } from "./compiler/FormalArgument.js"; import { InstanceScope } from "./InstanceScope.js"; import { Interpreter } from "./Interpreter.js"; import { ErrorManager } from "./misc/ErrorManager.js"; import { TypeRegistry } from "./misc/TypeRegistry.js"; import { ModelAdaptor } from "./ModelAdaptor.js"; import { Constructor } from "./reflection/IMember.js"; import { STErrorListener } from "./STErrorListener.js"; /** * A directory or directory tree of {@code .st} template files and/or group files. * Individual template files contain formal template definitions. In a sense, * it's like a single group file broken into multiple files, one for each template. * ST v3 had just the pure template inside, not the template name and header. * Name inside must match filename (minus suffix). */ export declare class STGroup { #private; static readonly GROUP_FILE_EXTENSION = ".stg"; static readonly TEMPLATE_FILE_EXTENSION = ".st"; /** When we use key as a value in a dictionary, this is how we signify. */ static readonly DICT_KEY = "key"; static readonly DEFAULT_KEY = "default"; static readonly DEFAULT_ERR_MGR: ErrorManager; /** Watch loading of groups and templates. */ static verbose: boolean; static defaultGroup: STGroup; /** The encoding to use for loading files. Defaults to UTF-8. */ encoding: string; delimiterStartChar: string; delimiterStopChar: string; /** * v3 compatibility; used to iterate across {@link Map#values()} instead of * v4's default {@link Map#keySet()}. * But to convert ANTLR templates, it's too hard to find without * static typing in templates. */ iterateAcrossValues: boolean; /** * The {@link ErrorManager} for entire group; all compilations and executions. * This gets copied to parsers, walkers, and interpreters. */ errMgr: ErrorManager; /** * Every group can import templates/dictionaries from other groups. * The list must be synchronized (see {@link STGroup#importTemplates}). */ readonly imports: ISTGroup[]; protected readonly importsToClearOnUnload: ISTGroup[]; /** Maps template name to {@link CompiledST} object (or null if a previous attempt to load it failed. */ protected templates: Map; /** * Maps dictionary names to {@link Map} objects representing the dictionaries * defined by the user like {@code typeInitMap ::= ["int":"0"]}. */ protected dictionaries: Map>; /** * A dictionary that allows people to register a renderer for * a particular kind of object for any template evaluated relative to this * group. For example, a date should be formatted differently depending * on the locale. You can set {@code Date.class} to an object whose * {@code toString(Object)} method properly formats a {@link Date} attribute * according to locale. Or you can have a different renderer object * for each locale. *

* Order of addition is recorded and matters. If more than one * renderer works for an object, the first registered has priority.

*

* Renderer associated with type {@code t} works for object {@code o} if

*
     *  t.isAssignableFrom(o.getClass()) // would assignment t = o work?
     *  
* So it works if {@code o} is subclass or implements {@code t}. *

* This structure is synchronized.

*/ protected renderers: Map>; /** * A dictionary that allows people to register a model adaptor for * a particular kind of object (subclass or implementation). Applies * for any template evaluated relative to this group. *

* ST initializes with model adaptors that know how to pull * properties out of {@link Object}s, {@link Map}s, and {@link ST}s.

*

* The last one you register gets priority; do least to most specific.

*/ protected readonly adaptors: TypeRegistry>; constructor(delimiterStartChar?: string, delimiterStopChar?: string); /** * Determines if a specified character may be used as a user-specified delimiter. * * @param c The character * @returns `true` if the character is reserved by the StringTemplate * language; otherwise, {@code false} if the character may be used as a * delimiter. * * @since 4.0.9 */ static isReservedCharacter(c: string): boolean; /** * The {@code "foo"} of {@code t() ::= "<@foo()>"} is mangled to * {@code "/region__/t__foo"} */ static getMangledRegionName(enclosingTemplateName: string, name: string): string; /** * Return {@code "t.foo"} from {@code "/region__/t__foo"} */ static getUnMangledTemplateName(mangledName: string): string; /** * The primary means of getting an instance of a template from this * group. Names must be absolute, fully-qualified names like {@code /a/b}. */ getInstanceOf(name: string): IST | null; /** * Create singleton template for use with dictionary values. */ createSingleton(templateToken: Token): IST; /** * Is this template defined in this group or from this group below? * Names must be absolute, fully-qualified names like {@code /a/b}. */ isDefined(name: string): boolean; /** * Look up a fully-qualified name. */ lookupTemplate(name: string): ICompiledST | null; /** * Unload all templates, dictionaries and import relationships, but leave * renderers and adaptors. This essentially forces the next call to * {@link #getInstanceOf} to reload templates. Call {@code unload()} on each * group in the {@link #imports} list, and remove all elements in * {@link #importsToClearOnUnload} from {@link #imports}. */ unload(): void; /** * Load st from disk if directory or load whole group file if .stg file (then * return just one template). {@code name} is fully-qualified. */ load(): void; load(name: string): ICompiledST | undefined | null; rawGetTemplate(name: string): ICompiledST | undefined | null; rawGetDictionary(name: string): Map | undefined; isDictionary(name: string): boolean; /** for testing */ defineTemplate(templateName: string, template: string): ICompiledST; defineTemplate(name: string, argsS: string, template: string): ICompiledST; defineTemplate(fullyQualifiedTemplateName: string, nameT: Token, args: FormalArgument[] | undefined, template: string, templateToken?: Token): ICompiledST; /** * Make name and alias for target. Replace any previous definition of name. */ defineTemplateAlias(aliasT: Token, targetT: Token): ICompiledST | undefined; defineRegion(enclosingTemplateName: string, regionT: Token, template: string, templateToken: Token): void; defineTemplateOrRegion(fullyQualifiedTemplateName: string, regionSurroundingTemplateName: string | undefined, templateToken: Token, template: string, nameToken: Token, args?: FormalArgument[]): void; rawDefineTemplate(name: string, code: ICompiledST, defT?: Token): void; undefineTemplate(name: string): void; /** * Compile a template. */ compile(params: ICompilerParameters): ICompiledST | undefined; /** * Define a map for this group. *

* Not thread safe...do not keep adding these while you reference them.

*/ defineDictionary(name: string, mapping: Map): void; /** * Make this group import templates/dictionaries from {@code g}. *

* On unload imported templates are unloaded but stay in the {@link #imports} list.

*/ importTemplates(g: STGroup): void; /** * Import template files, directories, and group files. * Priority is given to templates defined in the current group; * this, in effect, provides inheritance. Polymorphism is in effect so * that if an inherited template references template {@code t()} then we * search for {@code t()} in the subgroup first. *

* Templates are loaded on-demand from import dirs. Imported groups are * loaded on-demand when searching for a template.

*

* The listener of this group is passed to the import group so errors * found while loading imported element are sent to listener of this group.

*

* On unload imported templates are unloaded and removed from the imports * list.

*

* This method is called when processing import statements specified in * group files. Use {@link #importTemplates(STGroup)} to import templates * 'programmatically'.

*/ importTemplates(fileNameToken: Token): void; importTemplates(g: ISTGroup, clearOnUnload: boolean): void; getImportedGroups(): ISTGroup[]; /** * Load a group file with full path {@code fileName}; it's relative to root by {@code prefix}. */ loadGroupFile(prefix: string, fileName: string): void; /** * Load template file into this group using absolute {@code fileName}. */ loadAbsoluteTemplateFile(fileName: string): ICompiledST | undefined; /** * Load template stream into this group. {@code unqualifiedFileName} is * {@code "a.st"}. The {@code prefix} is path from group root to * {@code unqualifiedFileName} like {@code "/subdir"} if file is in * {@code /subdir/a.st}. */ loadTemplateFile(prefix: string, unqualifiedFileName: string, templateStream: CharStream): ICompiledST | undefined; /** * Add an adaptor for a kind of object so ST knows how to pull properties * from them. Add adaptors in increasing order of specificity. ST adds * {@link Object}, {@link Map}, {@link ST}, and {@link Aggregate} model * adaptors for you first. Adaptors you add have priority over default * adaptors. *

* If an adaptor for type {@code T} already exists, it is replaced by the * {@code adaptor} argument.

*

* This must invalidate cache entries, so set your adaptors up before * calling {@link ST#render} for efficiency.

*/ registerModelAdaptor(attributeType: Constructor, adaptor: ModelAdaptor): void; getModelAdaptor(attributeType: Constructor): ModelAdaptor; /** * Register a renderer for all objects of a particular "kind" for all * templates evaluated relative to this group. Use {@code r} to render if * object in question is an instance of {@code attributeType}. Recursively * set renderer into all import groups. */ registerRenderer(attributeType: Constructor, r: AttributeRenderer, recursive?: boolean): void; /** * Get renderer for class {@code T} associated with this group. *

* For non-imported groups and object-to-render of class {@code T}, use renderer * (if any) registered for {@code T}. For imports, any renderer * set on import group is ignored even when using an imported template. * You should set the renderer on the main group * you use (or all to be sure). I look at import groups as * "helpers" that should give me templates and nothing else. If you * have multiple renderers for {@code String}, say, then just make uber combined * renderer with more specific format names.

*/ getAttributeRenderer(attributeType: Constructor): AttributeRenderer | undefined; /** * Differentiate so we can avoid having creation events for regions, * map operations, and other implicit "new ST" events during rendering. */ createStringTemplateInternally(implOrProto?: ICompiledST | IST): IST; getName(): string; getFileName(): string | undefined; /** * Return root dir if this is group dir; return dir containing group file * if this is group file. This is derived from original incoming * dir or filename. If it was absolute, this should come back * as full absolute path. If only a URL is available, return URL of * one dir up. */ getRootDir(): string; toString(): string; show(): string; getListener(): STErrorListener; setListener(listener: STErrorListener): void; getTemplateNames(): Set; getEmbeddedInstanceOf(interp: Interpreter, scope: InstanceScope, name: string): IST; lookupImportedTemplate(name: string): ICompiledST | null; }