Playing with the QML/JS plugin
Sven Brauch
svenbrauch at googlemail.com
Mon Apr 7 20:38:54 UTC 2014
Hi,
On Monday 07 April 2014 22:10:58 Denis Steckelmacher wrote:
> I've pushed an experimental branch of the QML/JS plugin in
> kde:scratch/dsteckelmacher/kdev-qmljs, branch "experiments". This branch
> contains one commit that is mostly the result of me playing with the
> plugin and the DUChain for a day.
Awesome! Would you mind picking out things you think are working into separate
commits and maybe submitting them to reviewboard for example?
> My patch mostly moves code around (it removes expressionvisitor.cpp and
> merges its code into declarationbuilder.cpp, the commit message explains
> why) and adds some small type inference features.
Intuitively, I'm skeptical about whether that is going to work. In other
languages (when I say that, I mostly speak about python ;) the Expression
visitor is used to get the type of an expression in a variety of places. For
example, when I have a = 3 I create an expression visitor to visit the 3, then
assign the type to the variable. However, when I have foo.append(3), then
maybe I want to add the type of 3 to the list content type of foo. Having a
tool which allows to do "determine the type of this expression and return it"
is very flexible and usable in a variety of situations.
You might be able to replace that flexibility partially by what you're doing
now -- storing the types of nodes in those nodes themselves. I can't really
judge whether this is "good enough", though. For example, for code completion
it sounds a bit difficult to re-use (you don't want to run the declaration
builder on the expressions you handle in completion).
What motivated you to remove the expression visitor? Why is it an advantage?
> For instance, the
> plugin is now able to correctly guess the types of all these variables :
>
> // Variables that were already guessed before my patch
> var a = 5; // int
> var b = a; // int
> var f = function() { return "hello" }; // function string()
> var c = f(); // string
>
> // Variable not guessed correctly by ExpressionVisitor
> var d = (a == b); // ExpressionVisitor::lastType guessed int
>
> // Things that were not previously guessed
> var e = (a > b); // bool
> var f = (aFunction() & 0x1) // int
> var g = (function() { return c; })(); // string
>
> The whole testsuite of the plugin passes without failure, and I've added
> two tests (one for the variable "g" of my example, and one for "d" which
> was wrongly guessed).
Great, especially that you added tests ;)
> (for instance, I never know
> where I have to hold a DUChain read lock, therefore many of them may be
> missing).
Me neither *cough* :D
In more seriousness, whenever you have pointers to duchain objects around
(e.g. Declaration*) you generally need to hold a read lock, and when you
change anything which is already in the persistent database you need a write
lock. It is a bit unclear how strict the former is in the parsejob though,
there would be some investigation needed eventually -- which is probably
difficult :(
In any case, if you compile kdevplatform in debug mode, it will assert in
almost all situations where you do it wrong. There's very little chances for
screwing this up.
> As the type inference system and the declaration builder are
> now intertwined, I also had to declare variables and QML fields in
> endVisit() instead of visit(), because the types get known only when
> endVisit() is called. I would appreciate any comment on what I've done :-) .
To me it seems like all those problems are generally avoided by having the
expression visitor separate. Because then when you visit e.g. an assignment (a
= 3) you can just do
ExpressionVisitor v(assignment->rhs);
lhs_decl->setType(v.type());
or so.
> * Can I change the type of a declaration once it has been closed (for
> instance, by using getDeclaration(...)->setType(new_type))? This would
> allow me to guess that a in "var a; a = 5" is of type int, and it would
> be especially useful for setting the type of function parameters once
> they are used in a context were their type becomes evident.
Yes, you can do that at any time. Make sure to look at how unsure types work,
too, those are important for dynamic languages ;)
> * Is it possible for a declaration to have a source range outside the
> range of its parent context? It would be very useful to implement things
> like "var a = {}; a.b = 5;", with b being a field declared in the {}
> context created in the first statement.
I'm not 100% sure but I think no, not so easily. I think we already discussed
this as a possible issue a while back in IRC, no? Much of the duchain, esp.
its memory management (cleanup logic) is built around having everything nicely
ordered and nested range-wise. Python has an ugly hack for allowing pretty
much exactly this (declaring class members from outside the class context). We
should investigate if we can find a more proper solution some day, now that
more languages than just one need this.
Greetings!
Sven
More information about the KDevelop-devel
mailing list