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.