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  }