Le 07/09/2012 00:49, Lex Trotman a écrit :
On 7 September 2012 04:58, Colomban Wendling lists.ban@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@uvena.de https://lists.uvena.de/cgi-bin/mailman/listinfo/geany
Geany mailing list Geany@uvena.de https://lists.uvena.de/cgi-bin/mailman/listinfo/geany