19
19
#ifndef SWIFT_IMPORT_H
20
20
#define SWIFT_IMPORT_H
21
21
22
+ #include " swift/AST/Identifier.h"
23
+ #include " swift/Basic/Located.h"
24
+ #include " llvm/ADT/ArrayRef.h"
25
+ #include " llvm/ADT/SmallVector.h"
26
+ #include " llvm/ADT/STLExtras.h"
27
+
22
28
namespace swift {
29
+ class ASTContext ;
30
+
23
31
// / Describes what kind of name is being imported.
24
32
// /
25
33
// / If the enumerators here are changed, make sure to update all diagnostics
@@ -35,6 +43,291 @@ enum class ImportKind : uint8_t {
35
43
Func
36
44
};
37
45
46
+ namespace detail {
47
+ using ImportPathElement = Located<Identifier>;
48
+ using ImportPathRaw = llvm::ArrayRef<ImportPathElement>;
49
+
50
+ template <typename Subclass>
51
+ class ImportPathBase {
52
+ public:
53
+ using Element = ImportPathElement;
54
+ using Raw = ImportPathRaw;
55
+
56
+ protected:
57
+ Raw raw;
58
+
59
+ ImportPathBase (Raw raw) : raw(raw) { }
60
+
61
+ public:
62
+ const Raw &getRaw () const { return raw; }
63
+
64
+ Raw::iterator begin () const {
65
+ return raw.begin ();
66
+ }
67
+
68
+ Raw::iterator end () const {
69
+ return raw.end ();
70
+ }
71
+
72
+ const Element &operator [](size_t i) const { return raw[i]; }
73
+ bool empty () const { return raw.empty (); }
74
+ size_t size () const { return raw.size (); }
75
+
76
+ const Element &front () const { return raw.front (); }
77
+ const Element &back () const { return raw.back (); }
78
+
79
+ // / True if \c this and \c other are precisely equal, including SourceLocs.
80
+ bool operator ==(const Subclass &other) const {
81
+ return raw == other.raw ;
82
+ }
83
+
84
+ // / True if \c this and \c other contain the same identifiers in the same
85
+ // / order, ignoring SourceLocs.
86
+ bool isSameAs (const Subclass &other) const {
87
+ return size () == other.size ()
88
+ && std::equal (this ->begin (), this ->end (), other.begin (),
89
+ [](const Element &l, const Element &r) -> bool {
90
+ return l.Item == r.Item ;
91
+ }
92
+ );
93
+ }
94
+
95
+ Subclass getTopLevelPath () const {
96
+ assert (size () >= 1 && " nothing to take" );
97
+ return Subclass (raw.take_front ());
98
+ }
99
+
100
+ Subclass getParentPath () const {
101
+ assert (size () >= 0 && " nothing to take" );
102
+ return Subclass (raw.drop_back ());
103
+ }
104
+
105
+ SourceRange getSourceRange () const {
106
+ if (empty ()) return SourceRange ();
107
+ return SourceRange (raw.front ().Loc , raw.back ().Loc );
108
+ }
109
+ };
110
+
111
+ ImportPathRaw ImportPathBuilder_copyToImpl (ASTContext &ctx,
112
+ ImportPathRaw raw);
113
+
114
+ template <typename Subclass>
115
+ class ImportPathBuilder {
116
+ llvm::SmallVector<ImportPathElement, 4 > scratch;
117
+
118
+ public:
119
+ Subclass get () const {
120
+ return Subclass (scratch);
121
+ }
122
+
123
+ Subclass copyTo (ASTContext &ctx) const {
124
+ return Subclass (ImportPathBuilder_copyToImpl (ctx, scratch));
125
+ }
126
+
127
+ ImportPathBuilder () : scratch() { }
128
+ ImportPathBuilder (const ImportPathElement &elem) : scratch() {
129
+ scratch = { elem };
130
+ }
131
+ ImportPathBuilder (Identifier name, SourceLoc loc = SourceLoc())
132
+ : ImportPathBuilder(ImportPathElement(name, loc)) { }
133
+
134
+ template <typename Iterator>
135
+ ImportPathBuilder (Iterator begin, Iterator end) : scratch(begin, end) { }
136
+
137
+ template <typename Range>
138
+ ImportPathBuilder (Range collection)
139
+ : scratch(collection.begin(), collection.end()) { }
140
+
141
+ void push_back (const ImportPathElement &elem) { scratch.push_back (elem); }
142
+ void push_back (Identifier name, SourceLoc loc = SourceLoc()) {
143
+ scratch.push_back ({ name, loc });
144
+ }
145
+
146
+ void pop_back () { scratch.pop_back (); }
147
+
148
+ bool empty () const { return scratch.empty (); }
149
+ size_t size () const { return scratch.size (); }
150
+
151
+ llvm::SmallVector<ImportPathElement, 4 >::iterator begin () {
152
+ return scratch.begin ();
153
+ }
154
+ llvm::SmallVector<ImportPathElement, 4 >::iterator end () {
155
+ return scratch.end ();
156
+ }
157
+
158
+ const ImportPathElement &front () const { return scratch.front (); }
159
+ ImportPathElement &front () { return scratch.front (); }
160
+ const ImportPathElement &back () const { return scratch.back (); }
161
+ ImportPathElement &back () { return scratch.back (); }
162
+
163
+ template <typename Iterator>
164
+ void append (Iterator begin, Iterator end) {
165
+ scratch.append (begin, end);
166
+ }
167
+
168
+ template <typename Range>
169
+ void append (Range collection) {
170
+ append (collection.begin (), collection.end ());
171
+ }
172
+ };
173
+ }
174
+
175
+ // / An undifferentiated series of dotted identifiers in an \c import statement,
176
+ // / like \c Foo.Bar. Each identifier is packaged with its corresponding source
177
+ // / location.
178
+ // /
179
+ // / The first element of an \c ImportPath is always a top-level module name. The
180
+ // / remaining elements could specify a scope (naming a declaration in the
181
+ // / module) or a chain of submodule names. \c ImportPath does not differentiate
182
+ // / between these cases; its \c getModule() and \c getAccess() methods take an
183
+ // / \c ImportKind parameter to decide how to divvy up these identifiers.
184
+ // /
185
+ // / \c ImportPath is only used when analyzing the parsed representation of code.
186
+ // / Most code should use \c ImportPath::Module or \c ImportPath::Access, which
187
+ // / have semantic meaning.
188
+ // /
189
+ // / \c ImportPath is essentially a wrapper around \c ArrayRef and does not own
190
+ // / its elements, so something else needs to manage their lifetime.
191
+ // / \c ImportDecl owns the memory backing \c ImportDecl::getImportPath().
192
+ class ImportPath : public detail ::ImportPathBase<ImportPath> {
193
+ public:
194
+ // / A single dotted name from an \c ImportPath, \c ImportPath::Module, or
195
+ // / \c ImportPath::Access, with its source location.
196
+ using Element = detail::ImportPathBase<ImportPath>::Element;
197
+
198
+ // / The backing type for \c ImportPath, \c ImportPath::Module, and
199
+ // / \c ImportPath::Access; namely, an \c ArrayRef of \c ImportPath::Elements.
200
+ using Raw = detail::ImportPathBase<ImportPath>::Raw;
201
+
202
+ // / A helper type which encapsulates a temporary vector and can produce an
203
+ // / import path from it. In addition to the obvious use in a temporary
204
+ // / variable, this type can be used mid-expression to produce an import path
205
+ // / that is valid until the end of the expression.
206
+ using Builder = detail::ImportPathBuilder<ImportPath>;
207
+
208
+ // / Represents an access path--the portion of an \c ImportPath which describes
209
+ // / the name of a declaration to scope the import to.
210
+ // /
211
+ // / \c ImportPath::Access is used in scoped imports to designate a specific
212
+ // / declaration inside the module. The import will only* cover this
213
+ // / declaration, and will import it with a higher "priority" than usual, so
214
+ // / name lookup will prefer it over identically-named declarations visible
215
+ // / through other imports.
216
+ // /
217
+ // / (* Not actually only--e.g. extensions will be imported too. The primary
218
+ // / use case for scoped imports is actually to resolve name conflicts, not to
219
+ // / reduce the set of visible declarations.)
220
+ // /
221
+ // / When \c ImportPath::Access is empty, this means the import covers all
222
+ // / declarations in the module.
223
+ // /
224
+ // / Although in theory Swift could support scoped imports of nested
225
+ // / declarations, in practice it currently only supports scoped imports of
226
+ // / top-level declarations. Reflecting this, \c ImportPath::Access is backed
227
+ // / by an \c ArrayRef, but it asserts that the access path has zero or one
228
+ // / elements.
229
+ // /
230
+ // / \c ImportPath::Access is essentially a wrapper around \c ArrayRef and does
231
+ // / not own its elements, so something else needs to manage their lifetime.
232
+ // / \c ImportDecl owns the memory backing \c ImportDecl::getDeclPath().
233
+ class Access : public detail ::ImportPathBase<Access> {
234
+ public:
235
+ // / A helper type which encapsulates a temporary vector and can produce a
236
+ // / scope path from it. In addition to the obvious use in a temporary
237
+ // / variable, this type can be used mid-expression to produce a scope path
238
+ // / that is valid until the end of the expression.
239
+ using Builder = detail::ImportPathBuilder<Access>;
240
+
241
+ Access (ImportPath::Raw raw) : ImportPathBase(raw) {
242
+ assert (size () <= 1 && " nested scoped imports are not supported" );
243
+ }
244
+
245
+ Access () : ImportPathBase({}) { }
246
+
247
+ // / Returns \c true if the scope of this import includes \c name. An empty
248
+ // / scope matches all names.
249
+ bool matches (DeclName name) const {
250
+ return empty () || DeclName (front ().Item ).matchesRef (name);
251
+ }
252
+ };
253
+
254
+ // / Represents a module path--the portion of an \c ImportPath which describes
255
+ // / the name of the module being imported, possibly including submodules.
256
+ // /
257
+ // / \c ImportPath::Module contains one or more identifiers. The first
258
+ // / identiifer names a top-level module. The second and subsequent
259
+ // / identifiers, if present, chain together to name a specific submodule to
260
+ // / import. (Although Swift modules cannot currently contain submodules, Swift
261
+ // / can import Clang submodules.)
262
+ // /
263
+ // / \c ImportPath::Module is essentially a wrapper around \c ArrayRef and
264
+ // / does not own its elements, so something else needs to manage their
265
+ // / lifetime. \c ImportDecl owns the memory backing
266
+ // / \c ImportDecl::getModulePath().
267
+ class Module : public detail ::ImportPathBase<Module> {
268
+ public:
269
+ // / A helper type which encapsulates a temporary vector and can produce a
270
+ // / module path from it. In addition to the obvious use in a temporary
271
+ // / variable, this type can be used mid-expression to produce a module path
272
+ // / that is valid until the end of the expression.
273
+ using Builder = detail::ImportPathBuilder<Module>;
274
+
275
+ Module (ImportPath::Raw raw) : ImportPathBase(raw) {
276
+ assert (size () >= 1 && " must have a top-level module" );
277
+ }
278
+
279
+ // Note: This type does not have a constructor which just takes an
280
+ // `Identifier` because it would not be able to create a temporary
281
+ // `ImportPath::Element` with a long enough lifetime to return. Use
282
+ // `ImportPath::Module::Builder` to create a temporary module path.
283
+
284
+ bool hasSubmodule () const {
285
+ return size () != 1 ;
286
+ }
287
+
288
+ ImportPath::Raw getSubmodulePath () const {
289
+ return getRaw ().drop_front ();
290
+ }
291
+ };
292
+
293
+ ImportPath (Raw raw) : ImportPathBase(raw) {
294
+ assert (raw.size () >= 1 && " ImportPath must contain a module name" );
295
+ }
296
+
297
+ // / Extracts the portion of the \c ImportPath which represents a module name,
298
+ // / including submodules if appropriate.
299
+ Module getModulePath (bool isScoped) const {
300
+ if (isScoped)
301
+ return Module (getRaw ().drop_back ());
302
+
303
+ return Module (getRaw ());
304
+ }
305
+
306
+ // / Extracts the portion of the \c ImportPath which represents a scope for the
307
+ // / import.
308
+ Access getAccessPath (bool isScoped) const {
309
+ if (isScoped) {
310
+ assert (size () >= 2 && " scoped ImportPath must contain a decl name" );
311
+ return Access (getRaw ().take_back ());
312
+ }
313
+
314
+ return Access ();
315
+ }
316
+
317
+ // / Extracts the portion of the \c ImportPath which represents a module name,
318
+ // / including submodules, assuming the \c ImportDecl has the indicated
319
+ // / \c importKind.
320
+ Module getModulePath (ImportKind importKind) const {
321
+ return getModulePath (importKind != ImportKind::Module);
322
+ }
323
+
324
+ // / Extracts the portion of the \c ImportPath which represents a scope for the
325
+ // / import, assuming the \c ImportDecl has the indicated \c importKind.
326
+ Access getAccessPath (ImportKind importKind) const {
327
+ return getAccessPath (importKind != ImportKind::Module);
328
+ }
329
+ };
330
+
38
331
}
39
332
40
333
#endif
0 commit comments