/** * A `Dsymbol` representing a renamed import. * * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d) * Documentation: https://dlang.org/phobos/dmd_dimport.html * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dimport.d */ module dmd.dimport; import dmd.arraytypes; import dmd.dmodule; import dmd.dsymbol; import dmd.errors; import dmd.identifier; import dmd.location; import dmd.visitor; /*********************************************************** */ extern (C++) final class Import : Dsymbol { /* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2; */ Identifier[] packages; // array of Identifier's representing packages Identifier id; // module Identifier Identifier aliasId; int isstatic; // !=0 if static import Visibility visibility; // Pairs of alias=name to bind into current namespace Identifiers names; Identifiers aliases; Module mod; Package pkg; // leftmost package/module // corresponding AliasDeclarations for alias=name pairs AliasDeclarations aliasdecls; extern (D) this(const ref Loc loc, Identifier[] packages, Identifier id, Identifier aliasId, int isstatic) { Identifier selectIdent() { // select Dsymbol identifier (bracketed) if (aliasId) { // import [aliasId] = std.stdio; return aliasId; } else if (packages.length > 0) { // import [std].stdio; return packages[0]; } else { // import [id]; return id; } } super(loc, selectIdent()); assert(id); version (none) { import core.stdc.stdio; printf("Import::Import("); foreach (id; packages) { printf("%s.", id.toChars()); } printf("%s)\n", id.toChars()); } this.packages = packages; this.id = id; this.aliasId = aliasId; this.isstatic = isstatic; this.visibility = Visibility.Kind.private_; // default to private } extern (D) void addAlias(Identifier name, Identifier _alias) { if (isstatic) .error(loc, "%s `%s` cannot have an import bind list", kind, toPrettyChars); if (!aliasId) this.ident = null; // make it an anonymous import names.push(name); aliases.push(_alias); } override const(char)* kind() const { return isstatic ? "static import" : "import"; } override Visibility visible() pure nothrow @nogc @safe { return visibility; } // copy only syntax trees override Import syntaxCopy(Dsymbol s) { assert(!s); auto si = new Import(loc, packages, id, aliasId, isstatic); si.comment = comment; for (size_t i = 0; i < names.length; i++) { si.addAlias(names[i], aliases[i]); } return si; } /******************************* * Mark the imported packages as accessible from the current * scope. This access check is necessary when using FQN b/c * we're using a single global package tree. * https://issues.dlang.org/show_bug.cgi?id=313 */ extern (D) void addPackageAccess(ScopeDsymbol scopesym) { //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this); if (packages.length > 0) { // import a.b.c.d; auto p = pkg; // a scopesym.addAccessiblePackage(p, visibility); foreach (id; packages[1 .. $]) // [b, c] { auto sym = p.symtab.lookup(id); // https://issues.dlang.org/show_bug.cgi?id=17991 // An import of truly empty file/package can happen // https://issues.dlang.org/show_bug.cgi?id=20151 // Package in the path conflicts with a module name if (sym is null) break; // https://issues.dlang.org/show_bug.cgi?id=23327 // Package conflicts with symbol of the same name p = sym.isPackage(); if (p is null) break; scopesym.addAccessiblePackage(p, visibility); } } scopesym.addAccessiblePackage(mod, visibility); // d } override Dsymbol toAlias() { if (aliasId) return mod; return this; } override bool overloadInsert(Dsymbol s) { /* Allow multiple imports with the same package base, but disallow * alias collisions * https://issues.dlang.org/show_bug.cgi?id=5412 */ assert(ident && ident == s.ident); Import imp; if (!aliasId && (imp = s.isImport()) !is null && !imp.aliasId) return true; else return false; } override inout(Import) isImport() inout { return this; } override void accept(Visitor v) { v.visit(this); } }