kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/docs/schema/modules.txt (about)

     1  // Copyright 2020 The Kythe Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  Providing cross-references for module systems
    16  =============================================
    17  :Revision: 1.0
    18  :toc2:
    19  :toclevels: 3
    20  :priority: 999
    21  
    22  Many languages provide top-level mechanisms for organization that make
    23  writing large systems easier. These have explicit syntactic forms for
    24  expressing which components of a *module* are to be *exported* and which
    25  components are to be *imported* from other modules. It may also be possible
    26  to refer to the module itself as a first-class value in a program.
    27  
    28  In the following sections, we'll discuss common user expectations for
    29  cross-references in programs that use modules. The representation of a module
    30  itself is not in this document's scope.
    31  
    32  == Simple imports
    33  
    34  The second line makes the module named `fmt` available in scope as `fmt`. The
    35  exact semantics of what the local `fmt` is can differ depending on the
    36  language. In some languages, `fmt` is simply a local variable that points to
    37  the (first-class) module object; in others, it is part of a special category of
    38  identifiers that cannot be rebound. Users generally prefer to see any use of
    39  `fmt` *ref* the node representing the module's definition instead of the
    40  definition of the local alias, which may not even have a sensible syntactic
    41  location to anchor to:
    42  
    43  [source,go]
    44  ----
    45  import (
    46  //- @"\"fmt\"" ref/imports FmtModule
    47    "fmt"
    48  )
    49  //- @fmt ref FmtModule
    50  fmt.Sprint
    51  ----
    52  
    53  With these edges, users who attempt to navigate from the module's use site will
    54  be brought to the definition of `fmt`, not to the definition of the local
    55  alias. In the same way, users investigating cross-references from the module's
    56  definition will see every use of that module in the database (up to re-exporting
    57  and vexing control-flow), not just the places where it's been imported. In
    58  addition, other information (like documentation) will be available at every use
    59  site.
    60  
    61  Some languages allow particular values to be imported into local scope. These
    62  should be handled in the same way as module definitions:
    63  
    64  [source,javascript]
    65  ----
    66  //- @value ref/imports Value
    67  //- @"'./module'" ref/imports Module
    68  import {value} from './module';
    69  //- @value ref Value
    70  value;
    71  ----
    72  
    73  == Imports with renaming
    74  
    75  It's sometimes possible (or is even required) to choose a different name for the
    76  local binding created by an import from the target definition's. In this case,
    77  the local name *does* have a sensible syntactic location and is semantically
    78  relevant to the programmer. A use site of the local name refers to the local
    79  alias, which in turn aliases the module (or value) being imported.
    80  
    81  [source,javascript]
    82  ----
    83  //- @"'./module'" ref/imports Module
    84  //- @defaultExport defines/binding DefaultExport
    85  //- DefaultExport aliases DefaultExportDef
    86  //- DefaultExport.subkind import
    87  import defaultExport from './module';
    88  //- @"'./module'" ref/imports Module
    89  //- @mod_imp defines/binding ModImp
    90  //- ModImp aliases Module
    91  //- ModImp.subkind import
    92  import * as mod_imp from './module';
    93  //- @"'./module'" ref/imports Module
    94  //- @value ref/imports Value
    95  //- @renamedValue defines/binding RenamedValue
    96  //- RenamedValue aliases Value
    97  //- RenamedValue.subkind import
    98  import {value as renamedValue} from './module';
    99  //- @defaultExport ref DefaultExport
   100  defaultExport;
   101  //- @mod_imp ref ModImp
   102  mod_imp.foo;
   103  //- @renamedValue ref RenamedValue
   104  renamedValue;
   105  ----
   106  
   107  == Imports that do not create local bindings
   108  
   109  Languages like TypeScript allow modules to be imported strictly for their
   110  side-effects. In this case, only a `ref/imports` edge should be placed at
   111  the import site:
   112  
   113  [source,javascript]
   114  ----
   115  //- @"'./module'" ref/imports Module
   116  import './module';
   117  ----
   118  
   119  [source,go]
   120  ----
   121  //- @"\"lib/math\"" ref/imports MathModule
   122  import (
   123    _ "lib/math"
   124  )
   125  ----
   126  
   127  == Re-exporting and rebinding
   128  
   129  If a module re-exports a definition (renaming it or not) that it previously
   130  imported, that re-export site should be considered to be the definition of that
   131  name.
   132  
   133  If a program rebinds an imported name, indexers may treat the new name as a
   134  different variable:
   135  
   136  [source,javascript]
   137  ----
   138  //- @"'./module'" ref/imports Module
   139  //- @module defines/binding DefaultOne
   140  //- DefaultOne aliases DefaultOneDef
   141  import module from './module';
   142  //- @module ref DefaultOne
   143  module.foo();
   144  //- @"'./debug/module'" ref/imports DebugModule
   145  //- @module defines/binding DefaultTwo
   146  //- DefaultTwo aliases DefaultTwoDef
   147  import module from './debug/module';
   148  //- @module ref DefaultTwo
   149  //- ! { @module ref DefaultOne }
   150  module.foo();
   151  ----
   152  
   153  It may not be possible to determine that an import is changing, or to determine
   154  the value it's being changed to. In this case, indexers can treat import names
   155  like ordinary variables:
   156  
   157  [source,javascript]
   158  ----
   159  //- @"'./module'" ref/imports Module
   160  //- @module defines/binding ModuleImport
   161  //- ModuleImport.subkind import
   162  //- ModuleImport aliases Module
   163  import module from './module';
   164  //- @module ref ModuleImport
   165  if (random()) module = otherModule;
   166  //- @module ref ModuleImport
   167  module.foo();
   168  ----
   169  
   170  == Caveats
   171  
   172  Downstream consumers of the graph should tolerate overlapping references.
   173  Variables defined by imports should have subkind `import`. Consumers may
   174  choose to prioritize showing documentation or definitions of non-`import`
   175  nodes over `import` nodes.