Thread overview
using __traits to get line number of a member
Nov 13, 2021
forkit
Nov 13, 2021
Stanislav Blinov
Nov 13, 2021
forkit
Nov 13, 2021
Ali Çehreli
Nov 13, 2021
forkit
Nov 13, 2021
Stanislav Blinov
Nov 14, 2021
forkit
Nov 14, 2021
Stanislav Blinov
Nov 14, 2021
forkit
Nov 14, 2021
Ali Çehreli
November 13, 2021
Code below is self explanatory.

Any assistance on how to get the line number is welcome ;-)


// ++++++++++++++++++++++++++

module test;

import std;

class myClass{ void foo(){}}

void myFunction1(){}

void main()
{
    // list the first user defined member of this module (other than main)

    int i;
    foreach(m; __traits(allMembers, mixin(__MODULE__)))
    {
        // we can ignore these members
        // "std" and "object" are created by the compiler, and "main" I'm not interested in.
        if(m == "std" || m == "object" || m == "main")
        {
            i = 1;
            continue;
        }

        writefln("The name of the first user member is: %s", m);

        // On this next line, m.lineNumber is just a stub holder till an actual solution is found
        //writefln("The line number on which that member begins, is: %s, m.lineNumber);

        if(i == 1)
            break;
    }

    //writeln("Nothing to see here.");
}


void myFunction2(){}

// +++++++++++++++++++++++++
November 13, 2021
On Saturday, 13 November 2021 at 05:31:51 UTC, forkit wrote:
> Code below is self explanatory.
>
> Any assistance on how to get the line number is welcome ;-)

https://dlang.org/spec/traits.html#getLocation

That?
November 13, 2021
On Saturday, 13 November 2021 at 06:05:37 UTC, Stanislav Blinov wrote:
> On Saturday, 13 November 2021 at 05:31:51 UTC, forkit wrote:
>> Code below is self explanatory.
>>
>> Any assistance on how to get the line number is welcome ;-)
>
> https://dlang.org/spec/traits.html#getLocation
>
> That?

Thanks. That seems to be the one, except:

writeln(__traits(getLocation, m)[1]); // nope. writes the line no. of the foreach loop

writeln(__traits(getLocation, myClass)[1]); // yes, but I have to provide the name manually here, which i would not know.

I would have thought m referred to myClass at this point in the loop. But that doesn't seem to be the case.


November 12, 2021
On 11/12/21 11:00 PM, forkit wrote:

> // nope. writes the line no. of the foreach loop

mixin(m) seems to solve the issue, which I think necessitates 'static if':

    static foreach(m; __traits(allMembers, mixin(__MODULE__)))
    {
        static if(m == "std" || m == "object" || m == "main")
        {
          // Ignore
        } else {
          writefln("The name of the first user member is: %s", m);
          writeln(__traits(getLocation, mixin(m))[1]);  // <-- HERE
        }
    }

It works because we mix-in the value of the string 'm', which becomes a symbol.

('foreach' instead of 'static foreach' works as well.)

Ali

November 13, 2021
On Saturday, 13 November 2021 at 07:20:14 UTC, Ali Çehreli wrote:
>
> It works because we mix-in the value of the string 'm', which becomes a symbol.
>
> ('foreach' instead of 'static foreach' works as well.)
>
> Ali

Thanks. Really appreciate the help provided in this thread :-)

Final working code below:

//===================================

module test;

import std;

class myClass{ void foo(){}}

void myFunction1(){}

void main()
{
    // list the first user defined member of this module (other than main)

    int i;
    foreach(m; __traits(allMembers, mixin(__MODULE__)))
    {
        // ignore these members
        static if(m == "std" || m == "object" || m == "main" || m == "_d_run_main" || m == "_Dmain"  )
        {
           i = 1;
           continue;
        }
        else
        {
            writefln("The name of the first user member is: %s", m);

            // getLocation returns a tuple. See note below
            writefln("%s begins on line number: %s", m, __traits(getLocation, mixin(m))[1]);
        }

        if(i == 1) break;
    }
}


void myFunction2(){}


/*
    https://dlang.org/spec/traits.html#getLocation

    get the location of a symbol where the argument was declared.

    getLocation Returns a tuple(string, int, int) whose entries correspond to
    [0] string -> the filename
    [1] int -> line number
    [2] int -> column number
*/

// ======================================
November 13, 2021
On Saturday, 13 November 2021 at 08:04:56 UTC, forkit wrote:

>     int i;
>     foreach(m; __traits(allMembers, mixin(__MODULE__)))
>     // ...
>     __traits(getLocation, mixin(m))[1]);

What you really should be doing is this:

```d
static import mod = mixin(__MODULE__);
foreach (i, name; __traits(allMembers, mod))
{
   // ...
   __traits(getLocation, __traits(getMember, mod, i));
   // ...
}
```

Otherwise you might run into name conflicts, and get location of a wrong symbol.

Also if you really want to be generic you should couple it with `__traits(getOverloads)`, like the docs for getLocation suggest.
November 14, 2021
On Saturday, 13 November 2021 at 17:22:16 UTC, Stanislav Blinov wrote:
> On Saturday, 13 November 2021 at 08:04:56 UTC, forkit wrote:
>
>>     int i;
>>     foreach(m; __traits(allMembers, mixin(__MODULE__)))
>>     // ...
>>     __traits(getLocation, mixin(m))[1]);
>
> What you really should be doing is this:
>
> ```d
> static import mod = mixin(__MODULE__);
> foreach (i, name; __traits(allMembers, mod))
> {
>    // ...
>    __traits(getLocation, __traits(getMember, mod, i));
>    // ...
> }
> ```
>
> Otherwise you might run into name conflicts, and get location of a wrong symbol.
>
> Also if you really want to be generic you should couple it with `__traits(getOverloads)`, like the docs for getLocation suggest.

static import mod = mixin(__MODULE__);

That statement above would not compile. After spending way too much time trying to work out, I gave up, and used what i have, which works.

I just want to know, which members in my module are functions, and which are classes. I got the isFunction  (that method exists)

However, there is no isClass method. Why not?

How do I determine if a member is a class.. I wonder...

e.g.

//=========================
module test;

import std;

class myClass{} // nothing to see here

void main()
{
    alias allMembersOfThisModule = __traits(allMembers, mixin(__MODULE__));
    string memberFile() { return `__traits(getLocation, mixin(member))[0]`; }
    string memberLocation() { return `__traits(getLocation, mixin(member))[1]`; }

    foreach(member; allMembersOfThisModule)
    {
        static if(member == "std" || member == "object")
        {
            continue;
        }
        else
        {
            writefln("\nHere is a member: %s", member);

            // what kind of member is it?
            if(isFunction!(mixin(member)))
                writeln("This is a function.");
            //else
            //if(isClass!(mixin(member)))
               //writeln("This is a class.");
            else
                writeln("Not really sure what type of member this is..");

            writefln("%s is located in file: %s", member, mixin(memberFile));
            writefln("%s begins on line number: %s", member, mixin(memberLocation));
        }
    }
}

void myFunction(){} // nothing to see here

// =========================================
November 14, 2021
On Sunday, 14 November 2021 at 04:05:45 UTC, forkit wrote:

> However, there is no isClass method. Why not?
>
> How do I determine if a member is a class.. I wonder...

```
static if (is(something == class)) { /* ... */ }
```

or, if member is an instance

```
static if (is(typeof(something) == class)) { /* ... */ }
```

Ditto for interfaces, structs, unions.
November 14, 2021
On Sunday, 14 November 2021 at 04:24:09 UTC, Stanislav Blinov wrote:
> On Sunday, 14 November 2021 at 04:05:45 UTC, forkit wrote:
>
>> However, there is no isClass method. Why not?
>>
>> How do I determine if a member is a class.. I wonder...
>
> ```
> static if (is(something == class)) { /* ... */ }
> ```
>
> or, if member is an instance
>
> ```
> static if (is(typeof(something) == class)) { /* ... */ }
> ```
>
> Ditto for interfaces, structs, unions.

thanks :-)

works now...

if((is(mixin(member) == class)))
               writeln("This is a class.");

November 14, 2021
On 11/13/21 8:05 PM, forkit wrote:

> static import mod = mixin(__MODULE__);
>
> That statement above would not compile.

I don't understand myself but all of it as a single string works:

mixin("static import mod = " ~ __MODULE__ ~ ";");

Ali