diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 465837affc88..e11857c23dc6 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -8707,6 +8707,7 @@ struct Id final static Identifier* getVisibility; static Identifier* parent; static Identifier* child; + static Identifier* getModuleClasses; static Identifier* getMember; static Identifier* getOverloads; static Identifier* getVirtualFunctions; diff --git a/compiler/src/dmd/id.d b/compiler/src/dmd/id.d index ec5cb25ef28a..2eed152a8a64 100644 --- a/compiler/src/dmd/id.d +++ b/compiler/src/dmd/id.d @@ -462,6 +462,7 @@ immutable Msgtable[] msgtable = { "getVisibility" }, { "parent" }, { "child" }, + { "getModuleClasses" }, { "getMember" }, { "getOverloads" }, { "getVirtualFunctions" }, diff --git a/compiler/src/dmd/traits.d b/compiler/src/dmd/traits.d index e4eaa9c596e5..38f770b17a17 100644 --- a/compiler/src/dmd/traits.d +++ b/compiler/src/dmd/traits.d @@ -14,6 +14,7 @@ module dmd.traits; import core.stdc.stdio; +import core.stdc.string; import dmd.aggregate; import dmd.arraytypes; @@ -743,6 +744,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) auto se = new StringExp(e.loc, id.toString()); return se.expressionSemantic(sc); } + if (e.ident == Id.fullyQualifiedName) // https://dlang.org/spec/traits.html#fullyQualifiedName { if (dim != 1) @@ -779,6 +781,60 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return se.expressionSemantic(sc); } + + if (e.ident == Id.getModuleClasses) + { + /* https://dlang.org/spec/traits.html#getModuleClasses + */ + Module m; + if (dim == 0) + { + m = sc._module; // default to current module + if (!m) + return False(); + } + else if (dim == 1) + { + auto o = (*e.args)[0]; + auto s = getDsymbol(o); + if (s) + { + if (auto imp = s.isImport()) + m = imp.mod; + else + m = s.isModule(); + } + if (!m) + { + e.error("in expression `%s` `%s` must be a module", e.toChars(), o.toChars()); + return ErrorExp.get(); + } + } + else + return dimError(0); + + ClassDeclarations aclasses; + foreach (member; (*m.members)[]) + { + //printf("\tmember '%s'\n", member.toChars()); + member.addLocalClass(&aclasses); // same way genModuleInfo() does it + } + + auto exps = new Expressions(aclasses.length); + foreach (i, cd; aclasses) + { + const p = cd.toPrettyChars(); + //printf("class %s\n", p); + const s = p[0 .. strlen(p)]; + auto se = new StringExp(e.loc, s); + (*exps)[i] = se; + } + + Expression ex = new TupleExp(e.loc, exps); + ex = ex.expressionSemantic(sc); + return ex; + } + if (e.ident == Id.getProtection || e.ident == Id.getVisibility) { if (dim != 1) @@ -2244,7 +2300,7 @@ private void traitNotFound(TraitsExp e) initialized = true; // lazy initialization // All possible traits - __gshared Identifier*[59] idents = + __gshared Identifier*[60] idents = [ &Id.isAbstractClass, &Id.isArithmetic, @@ -2281,6 +2337,7 @@ private void traitNotFound(TraitsExp e) &Id.child, &Id.getLinkage, &Id.getMember, + &Id.getModuleClasses, &Id.getOverloads, &Id.getVirtualFunctions, &Id.getVirtualMethods, diff --git a/compiler/test/compilable/test23558.d b/compiler/test/compilable/test23558.d new file mode 100644 index 000000000000..c5942fae2460 --- /dev/null +++ b/compiler/test/compilable/test23558.d @@ -0,0 +1,17 @@ +/* TEST_OUTPUT: +--- +getModuleClasses: tuple("test23558.C") +getModuleClasses: tuple("std.stdio.StdioException") +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=23558 + +import std.stdio; + +class C { } + +pragma(msg, "getModuleClasses: ", __traits(getModuleClasses)); +pragma(msg, "getModuleClasses: ", __traits(getModuleClasses, std.stdio)); + +//pragma(msg, "getClassInfos: ", __traits(getModuleClasses, 3)); diff --git a/druntime/src/object.d b/druntime/src/object.d index 56e01ace2cb4..253470206125 100644 --- a/druntime/src/object.d +++ b/druntime/src/object.d @@ -246,7 +246,8 @@ class Object * } * --- */ - deprecated static Object factory(string classname) + deprecated("use __traits(getModuleClasses) instead") + static Object factory(string classname) { auto ci = TypeInfo_Class.find(classname); if (ci)