[Geany] Scoped Ruby declarations, with a hackish patch
Colomban Wendling
lists.ban at xxxxx
Fri Sep 7 00:22:23 UTC 2012
Le 07/09/2012 00:49, Lex Trotman a écrit :
> On 7 September 2012 04:58, Colomban Wendling <lists.ban at herbesfolles.org> 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
>> Geany at uvena.de
>> https://lists.uvena.de/cgi-bin/mailman/listinfo/geany
>>
>>
>>
>> _______________________________________________
>> Geany mailing list
>> Geany at uvena.de
>> https://lists.uvena.de/cgi-bin/mailman/listinfo/geany
More information about the Users
mailing list