kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/typescript/plugin_api.ts (about) 1 /* 2 * Copyright 2023 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @fileoverview This file contains interfaces and constants necessary to 19 * implement a plugin for TS indexing. 20 */ 21 22 import * as ts from 'typescript'; 23 24 import {JSONEdge, JSONFact, VName} from './kythe'; 25 import * as utf8 from './utf8'; 26 27 /** 28 * A unit of code that can be indexed. It resembles Kythe's CompilationUnit 29 * proto. 30 */ 31 export interface CompilationUnit { 32 /** 33 * A VName for the entire compilation, containing e.g. corpus name. Used as 34 * basis for all vnames emitted by indexer. 35 */ 36 rootVName: VName; 37 38 /** A map of file path to file-specific VName. */ 39 fileVNames: Map<string, VName>; 40 41 /** Files to index. */ 42 srcs: string[]; 43 44 /** 45 * List of files from which TS compiler will start type checking. It should 46 * include srcs files + file that provide global types, that are not imported 47 * from srcs files. All other dep files must be loaded following imports and 48 * by IndexingOptions.readFile function. 49 */ 50 rootFiles: string[]; 51 } 52 53 /** 54 * Various options that are required in order to perform indexing. 55 */ 56 export interface IndexingOptions { 57 /** Compiler options to use for indexing. */ 58 compilerOptions: ts.CompilerOptions; 59 60 /** 61 * Compiler host to use for indexing. Simplest approach is to create 62 * ts.createCompilerHost(options). In more advanced cases callers 63 * might augment host to cache commonly used libraries for example. 64 */ 65 compilerHost: ts.CompilerHost; 66 67 /** Function that receives final kythe indexing data. */ 68 emit: (obj: JSONFact|JSONEdge) => void; 69 70 /** 71 * If provided, a list of plugin indexers to run after the TypeScript program 72 * has been indexed. 73 */ 74 plugins?: Plugin[]; 75 76 /** 77 * If provided, a function that reads a file as bytes to a Node Buffer. It'd 78 * be nice to just reuse program.getSourceFile but unfortunately that returns 79 * a (Unicode) string and we need to get at each file's raw bytes for 80 * UTF-8<->UTF-16 conversions. If omitted - fs.readFileSync is used. 81 */ 82 readFile?: (path: string) => Buffer; 83 84 /** 85 * When enabled, ref/call source anchors span identifiers instead of full 86 * call expressions when possible. 87 */ 88 emitRefCallOverIdentifier?: boolean; 89 90 /** 91 * When enabled any error thrown from any plugin gets propagated to the caller. 92 * Currently errors from plugins are logged without interrupting analysis. 93 */ 94 failAnalysisOnPluginError?: boolean; 95 } 96 97 98 99 /** 100 * TSNamespace represents the three declaration namespaces of TypeScript: types, 101 * values, and (confusingly) namespaces. A given symbol may be a type, and/or a 102 * value, and/or a namespace. 103 * 104 * See the table at 105 * https://www.typescriptlang.org/docs/handbook/declaration-merging.html 106 * for a listing of namespace groups for various declaration types and further 107 * discussion. 108 * 109 * TYPE_MIGRATION is a temporary namespace to be used during the tvar migration. 110 */ 111 export enum TSNamespace { 112 TYPE, 113 VALUE, 114 NAMESPACE, 115 TYPE_MIGRATION, 116 } 117 118 /** 119 * Context represents the environment a node is declared in, and may be used for 120 * disambiguating a node's declarations if it has multiple. 121 */ 122 export enum Context { 123 /** 124 * No disambiguation about a node's declarations. May be lazily generated 125 * from other contexts; see SymbolVNameStore documentation. 126 */ 127 Any, 128 /** The node is declared as a getter. */ 129 Getter, 130 /** The node is declared as a setter. */ 131 Setter, 132 } 133 134 /** 135 * An indexer host holds information about the program indexing and methods 136 * used by the TypeScript indexer that may also be useful to plugins, reducing 137 * code duplication. 138 */ 139 export interface IndexerHost { 140 /** Compilation unit being indexed. */ 141 compilationUnit: CompilationUnit; 142 143 options: IndexingOptions; 144 145 /** 146 * Gets the offset table for a file path. 147 * These are used to lookup UTF-8 offsets (used by Kythe) from UTF-16 offsets 148 * (used by TypeScript), and vice versa. 149 */ 150 getOffsetTable(path: string): Readonly<utf8.OffsetTable>; 151 /** 152 * getSymbolAtLocation is the same as ts.TypeChecker.getSymbolAtLocation, 153 * except that it has a return type that properly captures that 154 * getSymbolAtLocation can return undefined. (The TypeScript API itself is 155 * not yet null-safe, so it hasn't been annotated with full types.) 156 */ 157 getSymbolAtLocation(node: ts.Node): ts.Symbol|undefined; 158 159 /** 160 * Similar to getSymbolAtLocation() if returned symbol is an alias. One 161 * example is imports: 162 * 163 * // a.ts 164 * export value = 42; // #1 165 * 166 * // b.ts 167 * import {value} from './a'; // #2 168 * console.log(value); // #3 169 * 170 * getSymbolAtLocationFollowingAliases for #3 will return #1 while regular 171 * getSymbolAtLocation returns #2. 172 */ 173 getSymbolAtLocationFollowingAliases(node: ts.Node): ts.Symbol|undefined; 174 175 /** 176 * Computes the VName (and signature) of a ts.Symbol. A Context can be 177 * optionally specified to help disambiguate nodes with multiple declarations. 178 * See the documentation of Context for more information. 179 */ 180 getSymbolName(sym: ts.Symbol, ns: TSNamespace, context?: Context): VName 181 |undefined; 182 /** 183 * scopedSignature computes a scoped name for a ts.Node. 184 * E.g. if you have a function `foo` containing a block containing a variable 185 * `bar`, it might return a VName like 186 * signature: "foo.block0.bar"" 187 * path: <appropriate path to module> 188 */ 189 scopedSignature(startNode: ts.Node): VName; 190 /** 191 * Converts a file path into a file VName. 192 */ 193 pathToVName(path: string): VName; 194 /** 195 * Returns the module name of a TypeScript source file. 196 * See moduleName() for more details. 197 */ 198 moduleName(path: string): string; 199 /** 200 * TypeScript program. 201 */ 202 program: ts.Program; 203 } 204 205 /** 206 * A indexer plugin adds extra functionality with the same inputs as the base 207 * indexer. 208 */ 209 export interface Plugin { 210 /** Name of the plugin. It will be printed to stderr when running plugin. */ 211 name: string; 212 /** 213 * Indexes a TypeScript program with extra functionality. 214 * Takes a indexer host, which provides useful properties and methods that 215 * the plugin can defer to rather than reimplementing. 216 */ 217 index(context: IndexerHost): void; 218 }