Skip to content

Commit

Permalink
Merge pull request #856 from adamdruppe/protection_trait
Browse files Browse the repository at this point in the history
Protection trait
  • Loading branch information
WalterBright committed Nov 11, 2012
2 parents c08223a + 2cb747d commit 913b485
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 20 deletions.
15 changes: 4 additions & 11 deletions src/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,17 +723,10 @@ void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
{
const char *p;

switch (protection)
{
case PROTprivate: p = "private"; break;
case PROTpackage: p = "package"; break;
case PROTprotected: p = "protected"; break;
case PROTpublic: p = "public"; break;
case PROTexport: p = "export"; break;
default:
assert(0);
break;
}
p = Pprotectionnames[protection];

assert(p);

buf->writestring(p);
buf->writeByte(' ');
}
Expand Down
9 changes: 1 addition & 8 deletions src/doc.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,15 +558,8 @@ void ScopeDsymbol::emitMemberComments(Scope *sc)

void emitProtection(OutBuffer *buf, PROT prot)
{
const char *p;
const char *p = Pprotectionnames[prot];

switch (prot)
{
case PROTpackage: p = "package"; break;
case PROTprotected: p = "protected"; break;
case PROTexport: p = "export"; break;
default: p = NULL; break;
}
if (p)
buf->printf("%s ", p);
}
Expand Down
3 changes: 3 additions & 0 deletions src/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ enum PROT
PROTexport,
};

// this is used for printing the protection in json, traits, docs, etc.
static const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};

/* State of symbol in winding its way through the passes of the compiler
*/
enum PASS
Expand Down
1 change: 1 addition & 0 deletions src/idgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ Msgtable msgtable[] =
{ "isLazy" },
{ "hasMember" },
{ "identifier" },
{ "getProtection" },
{ "parent" },
{ "getMember" },
{ "getOverloads" },
Expand Down
1 change: 0 additions & 1 deletion src/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const char Ptype[] = "type";
const char Pcomment[] = "comment";
const char Pmembers[] = "members";
const char Pprotection[] = "protection";
const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};

void JsonRemoveComma(OutBuffer *buf);

Expand Down
45 changes: 45 additions & 0 deletions src/traits.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,51 @@ Expression *TraitsExp::semantic(Scope *sc)
StringExp *se = new StringExp(loc, id->toChars());
return se->semantic(sc);
}
else if (ident == Id::getProtection)
{
if (dim != 1)
goto Ldimerror;
Object *o = (*args)[0];
Dsymbol *s = getDsymbol(o);
if(!s)
{
// it might also be a trait getMember or something,
// which returns a dot expression rather than a symbol
if(o->dyncast() == DYNCAST_EXPRESSION)
{
Expression *e = (Expression *) o;

if (e->op == TOKdotvar)
{
DotVarExp *dv = (DotVarExp *)e;
s = dv->var->isDeclaration();
}
}
}
if(!s)
{
bool gagError = false;
if(o->dyncast() == DYNCAST_EXPRESSION)
{
Expression *e = (Expression *) o;
if(e->op == TOKerror)
gagError = true;
}

if(!gagError)
error("argument %s has no protection", o->toChars());

goto Lfalse;
}

PROT protection = s->prot();

const char *protName = Pprotectionnames[protection];

StringExp *se = new StringExp(loc, (char *) protName);
return se->semantic(sc);
}

else if (ident == Id::parent)
{
if (dim != 1)
Expand Down
69 changes: 69 additions & 0 deletions test/runnable/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,75 @@ struct A8972

/********************************************************/

private struct TestProt1 {}
package struct TestProt2 {}
protected struct TestProt3 {}
public struct TestProt4 {}
export struct TestProt5 {}

void getProtection()
{
class Test
{
private { int va; void fa(){} }
package { int vb; void fb(){} }
protected { int vc; void fc(){} }
public { int vd; void fd(){} }
export { int ve; void fe(){} }
}
Test t;

// TOKvar and VarDeclaration
static assert(__traits(getProtection, Test.va) == "private");
static assert(__traits(getProtection, Test.vb) == "package");
static assert(__traits(getProtection, Test.vc) == "protected");
static assert(__traits(getProtection, Test.vd) == "public");
static assert(__traits(getProtection, Test.ve) == "export");

// TOKdotvar and VarDeclaration
static assert(__traits(getProtection, t.va) == "private");
static assert(__traits(getProtection, t.vb) == "package");
static assert(__traits(getProtection, t.vc) == "protected");
static assert(__traits(getProtection, t.vd) == "public");
static assert(__traits(getProtection, t.ve) == "export");

// TOKvar and FuncDeclaration
static assert(__traits(getProtection, Test.fa) == "private");
static assert(__traits(getProtection, Test.fb) == "package");
static assert(__traits(getProtection, Test.fc) == "protected");
static assert(__traits(getProtection, Test.fd) == "public");
static assert(__traits(getProtection, Test.fe) == "export");

// TOKdotvar and FuncDeclaration
static assert(__traits(getProtection, t.fa) == "private");
static assert(__traits(getProtection, t.fb) == "package");
static assert(__traits(getProtection, t.fc) == "protected");
static assert(__traits(getProtection, t.fd) == "public");
static assert(__traits(getProtection, t.fe) == "export");

// TOKtype
static assert(__traits(getProtection, TestProt1) == "private");
static assert(__traits(getProtection, TestProt2) == "package");
static assert(__traits(getProtection, TestProt3) == "protected");
static assert(__traits(getProtection, TestProt4) == "public");
static assert(__traits(getProtection, TestProt5) == "export");

// This specific pattern is important to ensure it always works
// through reflection, however that becomes implemented
static assert(__traits(getProtection, __traits(getMember, t, "va")) == "private");
static assert(__traits(getProtection, __traits(getMember, t, "vb")) == "package");
static assert(__traits(getProtection, __traits(getMember, t, "vc")) == "protected");
static assert(__traits(getProtection, __traits(getMember, t, "vd")) == "public");
static assert(__traits(getProtection, __traits(getMember, t, "ve")) == "export");
static assert(__traits(getProtection, __traits(getMember, t, "fa")) == "private");
static assert(__traits(getProtection, __traits(getMember, t, "fb")) == "package");
static assert(__traits(getProtection, __traits(getMember, t, "fc")) == "protected");
static assert(__traits(getProtection, __traits(getMember, t, "fd")) == "public");
static assert(__traits(getProtection, __traits(getMember, t, "fe")) == "export");
}

/********************************************************/

int main()
{
test1();
Expand Down

1 comment on commit 913b485

@TurkeyMan
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I was just thinking this would be really useful on Friday! ;)

Please sign in to comment.