Le 07/09/2012 00:49, Lex Trotman a écrit :
> On 7 September 2012 04:58, Colomban Wendling <[email protected]> 
> wrote:
>> Hi guys,
>>
>> I saw that the ruby parser don't properly generate tags declarations like:
>>
>>         class Foo::Bar
>>         end
>>
>> which should generate a tag "Bar" with the scope "Foo";  but it
>> generates a tag "Foo" and simply ignores "Bar".  This seems to apply to
>> modules, classes and methods at least -- almost everything.
>>
>> So I wanted to fix that.  Unfortunately the scoping code in CTags don't
>> really support to easily put several scopes at the same "level", e.g. if
>> you want to push several scope you gotta handle the popping yourself.
>> And since there is one single block end, it's tricky to do.
>>
>> Since I was way too lazy (and didn't even found a good implementation)
>> to fix that, I just did it the dirty way: reading the whole "Foo::Bar"
> 
> This is of course what C++ does when the declarations are not visible eg
> 
> a::b::f(){}; makes a function 'a::b::f' if the declarations of a and b
> are not visible (eg in a closed .hpp file), if they are visible it
> puts f inside the declaration of b. Compare the symbols pane entrys
> for the definitions of f() and g() in the attached.

I don't think you got what I meant.  I'm not talking about what you see
in the symbol list, I'm talking about how the tags get parsed.  Of
course the symbol list shows something like "A::B::C" if A and B are not
declared, but that's just because symbol C has scope A::B and we display
the scope if we can't display the actual parent.

OK, maybe I could take a look at how the C++ parser parses A::B::C,
maybe they have a better solution;  but what I'm saying is that the
parser first reads identifiers A, B and C and put them in a single
string (with a separator of course) as if it was the identifier itself,
and splits it back later in "A::B" and "C" and uses the first as an
additional scope and the last as the symbol name.  This means that if
the separator token ("::" in the example) can appear in a legitimate,
non-scoped identifier, it'd break.  And the code is quite ugly since it
first packs to later unpack.

A nicer approach would perhaps be to have a separation between blocks
and scope, e.g. a stack of blocks each accepting a multi-level scope,
instead of assuming block level == scope level.  Something like:

        struct Block {
                char *scope[];
                struct Block children[];
        }

thus the code:

        namespace Foo {}
        class Foo::Bar {
                class Baz {}
        }
        method Foo::Bar::something {}

would give:

        Block root = {
                .scope = {}
                .children = {
                        {
                                .scope = { "Foo" }
                                .children = {}
                        },
                        {
                                .scope = { "Foo", "Bar" },
                                .children = {
                                        {
                                                .scope = { "Baz" },
                                                .children = {}
                                        }
                                }
                        },
                        {
                                .scope = { "Foo", "Bar", "something" },
                                .children = {}
                        }
                }
        }

Of course in practice we only need one block (with parents) at a time,
so we could simply use a two-dimensional array instead of such a complex
tree.  E.g. hierarchy inside class Baz would be:

        { { "Foo", "Bar" }, { "Baz" } }

but if it was written like:

        namespace Foo {
                class Bar {
                        class Baz {}
                }
        }

the hierarchy would've been

        { { "Foo" }, { "Bar" }, { "Baz" } }

e.g. "classic", where each block level corresponds to only one scope --
like it is now.

But again, I'm only talking about how the parser is written.

> I'm not a rubyist but I assume that Foo doesn't need to be declared
> before Bar in the above example and thats the problem.  From the C++
> example what you would need to do is "autodeclare" Foo (as what?) so
> you had somewhere to put Bar.

Nope, basic test shows that Ruby wants the levels to be declared, so
there is no need for auto-declaration.  However I think Vala's
namespaces needs the feature, e.g. the following:

        namespace Foo.Bar {}

declares both namespaces Foo and Foo::Bar for that scope, and

        class Foo.Bar () {}

declares namespace Foo and class Foo::Bar.

>> as a single tag name ("Foo.Bar") and tuning the code registering the tag
>> to split this on the last ".", putting the left part (if any) in the
>> scope.  Patch attached.  This is quite dirty, but works fine unless a
>> legitimate tag may include a "." in its name, which doesn't seem the
>> case currently looking at the parser.
>>
>> Note that Ruby isn't the only language that allows such kind of scoping.
>>  For example, Vala allows to prefix stuff with a namespace -- and there
>> is the same problem here.
> 
> But it is statically declared so it should work like C++ should it not?

What do you mean?

> 
> Cheers
> Lex
> 
>>
>> So, especially Nick, what do you guys think of this?  Is this patch too
>> dirty?  Do somebody have a better idea?  Or is this too dirty and "we
>> don't care because nobody writes ruby anyway"?  In one word: opinions?
>>
>> Thanks,
>> Colomban
>>
>> _______________________________________________
>> Geany mailing list
>> [email protected]
>> https://lists.uvena.de/cgi-bin/mailman/listinfo/geany
>>
>>
>>
>> _______________________________________________
>> Geany mailing list
>> [email protected]
>> https://lists.uvena.de/cgi-bin/mailman/listinfo/geany

_______________________________________________
Geany mailing list
[email protected]
https://lists.uvena.de/cgi-bin/mailman/listinfo/geany

Reply via email to