2 * A `Dsymbol` representing a renamed import.
4 * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d)
8 * Documentation: https://dlang.org/phobos/dmd_dimport.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dimport.d
14 import dmd
.arraytypes
;
16 import dmd
.declaration
;
20 import dmd
.dsymbolsem
;
22 import dmd
.expression
;
24 import dmd
.identifier
;
29 import core
.stdc
.stdio
;
30 /***********************************************************
32 extern (C
++) final class Import
: Dsymbol
34 /* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2;
36 Identifier
[] packages
; // array of Identifier's representing packages
37 Identifier id
; // module Identifier
39 int isstatic
; // !=0 if static import
40 Visibility visibility
;
42 // Pairs of alias=name to bind into current namespace
47 Package pkg
; // leftmost package/module
49 // corresponding AliasDeclarations for alias=name pairs
50 AliasDeclarations aliasdecls
;
52 extern (D
) this(const ref Loc loc
, Identifier
[] packages
, Identifier id
, Identifier aliasId
, int isstatic
)
54 Identifier
selectIdent()
56 // select Dsymbol identifier (bracketed)
59 // import [aliasId] = std.stdio;
62 else if (packages
.length
> 0)
64 // import [std].stdio;
74 super(loc
, selectIdent());
79 printf("Import::Import(");
80 foreach (id
; packages
)
82 printf("%s.", id
.toChars());
84 printf("%s)\n", id
.toChars());
86 this.packages
= packages
;
88 this.aliasId
= aliasId
;
89 this.isstatic
= isstatic
;
90 this.visibility
= Visibility
.Kind
.private_
; // default to private
93 extern (D
) void addAlias(Identifier name
, Identifier _alias
)
96 .error(loc
, "%s `%s` cannot have an import bind list", kind
, toPrettyChars
);
98 this.ident
= null; // make it an anonymous import
100 aliases
.push(_alias
);
103 override const(char)* kind() const
105 return isstatic ?
"static import" : "import";
108 override Visibility
visible() pure nothrow @nogc @safe
113 // copy only syntax trees
114 override Import
syntaxCopy(Dsymbol s
)
117 auto si
= new Import(loc
, packages
, id
, aliasId
, isstatic
);
118 si
.comment
= comment
;
119 for (size_t i
= 0; i
< names
.length
; i
++)
121 si
.addAlias(names
[i
], aliases
[i
]);
126 /*******************************
129 * true for errors, false for success
131 extern (D
) bool load(Scope
* sc
)
133 //printf("Import::load('%s') %p\n", toPrettyChars(), this);
134 // See if existing module
135 const errors
= global
.errors
;
136 DsymbolTable dst
= Package
.resolve(packages
, null, &pkg
);
139 if (pkg
&& pkg
.isModule())
141 .error(loc
, "can only import from a module, not from a member of module `%s`. Did you mean `import %s : %s`?", pkg
.toChars(), pkg
.toPrettyChars(), id
.toChars());
142 mod
= pkg
.isModule(); // Error recovery - treat as import of that module
146 Dsymbol s
= dst
.lookup(id
);
153 if (s
.isAliasDeclaration())
155 .error(loc
, "%s `%s` conflicts with `%s`", s
.kind(), s
.toPrettyChars(), id
.toChars());
157 else if (Package p
= s
.isPackage())
159 if (p
.isPkgMod
== PKG
.unknown
)
161 uint preverrors
= global
.errors
;
162 mod
= Module
.load(loc
, packages
, id
);
164 p
.isPkgMod
= PKG
.package_
;
167 // mod is a package.d, or a normal module which conflicts with the package name.
168 if (mod
.isPackageFile
)
169 mod
.tag
= p
.tag
; // reuse the same package tag
172 // show error if Module.load does not
173 if (preverrors
== global
.errors
)
174 .error(loc
, "%s `%s` from file %s conflicts with %s `%s`", mod
.kind(), mod
.toPrettyChars(), mod
.srcfile
.toChars
, p
.kind(), p
.toPrettyChars());
181 mod
= p
.isPackageMod();
185 .error(loc
, "can only import from a module, not from package `%s.%s`", p
.toPrettyChars(), id
.toChars());
190 .error(loc
, "can only import from a module, not from package `%s.%s`", pkg
.toPrettyChars(), id
.toChars());
194 .error(loc
, "can only import from a module, not from package `%s`", id
.toChars());
201 mod
= Module
.load(loc
, packages
, id
);
204 // id may be different from mod.ident, if so then insert alias
208 if (mod
&& !mod
.importedFrom
)
209 mod
.importedFrom
= sc ? sc
._module
.importedFrom
: Module
.rootModule
;
212 if (mod
&& mod
.isPackageFile
)
214 // one level depth package.d file (import pkg; ./pkg/package.d)
215 // it's necessary to use the wrapping Package already created
221 //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
222 return global
.errors
!= errors
;
225 /*******************************
226 * Mark the imported packages as accessible from the current
227 * scope. This access check is necessary when using FQN b/c
228 * we're using a single global package tree.
229 * https://issues.dlang.org/show_bug.cgi?id=313
231 extern (D
) void addPackageAccess(ScopeDsymbol scopesym
)
233 //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this);
234 if (packages
.length
> 0)
238 scopesym
.addAccessiblePackage(p
, visibility
);
239 foreach (id
; packages
[1 .. $]) // [b, c]
241 auto sym
= p
.symtab
.lookup(id
);
242 // https://issues.dlang.org/show_bug.cgi?id=17991
243 // An import of truly empty file/package can happen
244 // https://issues.dlang.org/show_bug.cgi?id=20151
245 // Package in the path conflicts with a module name
248 // https://issues.dlang.org/show_bug.cgi?id=23327
249 // Package conflicts with symbol of the same name
253 scopesym
.addAccessiblePackage(p
, visibility
);
256 scopesym
.addAccessiblePackage(mod
, visibility
); // d
259 override Dsymbol
toAlias()
266 override bool overloadInsert(Dsymbol s
)
268 /* Allow multiple imports with the same package base, but disallow
270 * https://issues.dlang.org/show_bug.cgi?id=5412
272 assert(ident
&& ident
== s
.ident
);
274 if (!aliasId
&& (imp
= s
.isImport()) !is null && !imp
.aliasId
)
280 override inout(Import
) isImport() inout
285 override void accept(Visitor v
)