Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protection trait #856

Merged
merged 2 commits into from
Nov 11, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions src/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,17 +683,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 @@ -553,15 +553,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 @@ -322,6 +322,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 @@ -206,6 +206,51 @@ Expression *TraitsExp::semantic(Scope *sc)
StringExp *se = new StringExp(loc, s->ident->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 @@ -729,6 +729,75 @@ void test7608()

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

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