[cfe-dev] Qt 4 to Qt 5 porting tool with the tooling branch
klimek at google.com
Mon Jun 18 05:46:43 PDT 2012
first, really cool blog post, and thanks for providing feedback & docs and
helping us making the tools more awesome - we really appreciate this!
On Mon, Jun 18, 2012 at 1:22 PM, Stephen Kelly <steveire at gmail.com> wrote:
> Hi there,
> A few weeks ago I was getting started with the tooling branch to do some
> porting from Qt 4 to Qt 5 (I was off topic though :)):
> I wrote a blog post with some results here:
> I also wrote the following to colleagues, and thought I'd get some fact
> checking on it from the people who might know, so that the new API in the
> branch can be documented better:
> [Begin copy-paste]
> The tool works by using the CMake integration to find out what command
> should be used to compile the file passed to it for porting. It then parses
> that file and runs a visitor pattern over the parsed AST. While visiting,
> checks to see if the node matches what was specified. When it gets a match
> it invokes the run() method of a callback.
> The run() method is the one that sets up a replacement for the matched AST
> node with some text. The text can be the new method being ported to, or
> other generated string.
> The matched nodes can be extracted by their id and type. The type takes a
> while to get used to because there are many of them describing all the
> different parts of C++ syntax.
> Once we have the replacement text, we add it to the Replacements structure,
> which is processed after matching to to the actual changes.
> Knowing how to write a matcher or what type to use to extract a node by id
> can be tricky, but can be made easier by running 'clang -cc1 -ast-dump
> myfile.cpp' to see what types the parser sees.
> After that, the matches are actually nested function calls (the
> capitalisation style for functions seems funny to use Qt developers).
Yea, that's not set yet - please chime in with your color of the bikeshed
on the review thread for the ast matchers ;) I seriously don't care, so I
want people who care about one way or the other to jump in with good
arguments of why their preferred way is superior :D
> matches are usually specializations.
> matches any expression. As does
> The inner one is redundant.
> matches an expression which is a function, not an expression which contains
> inside it a function.
> child relationships are found with has()
> finds for example
> where foo() would be the Expression() and bar() would be the Function().
> To use these in the callback, we would write
> Id("expr", Expression(has(Id("func", Function()))))
> and then
> const Expr *Outer =
> const Expr *Inner =
> Match expressions next to each other are by default grouped in an AllOf
> means 'A method with the name dataChanged where that method is on a class
> derived from QAbstractItemView'
> You do get interesting compile errors sometimes when writing matcher
> constructs. With enough playing around and reading other matchers I've been
> able to get it to do what I want each time eventually, and the result was
> obvious why it was correct.
> Apart from the code I've attached, to see what's possible (built in), you
> reference the following:
> # This is the one referenced in the youtube talk above:
> # Most of the implementation
> # Unit tests
> [End copy-paste]
> I was also wondering if there is an easy way to only modify the code inside
> the repo and not included headers? In my tool I require the user to pass
> source-dir on the command line, and then manually check paths to see if
> are below it, but this is error-prone.
If with "manually", you mean "do a regexp match on the path", then yep,
that's what I also do.
Why is that error prone?
> Additionally, many of the concepts I encoded are generic, not Qt specific
> (such as renaming methods, enums etc). It seems that these could be re-
> usable, so we could either add some version of this to the clang examples,
> and/or see if we can define a higher level collection of ways to refactor
> the code. I presume google also has some collection/repo of such things
Unfortunately not. Most of the engineers using those tools at Google have
pretty non-standard and complex problems, at which point other costs start
to dwarf writing the matchers and replacements.
But we are starting to work on a more principled approach that includes
ready-made refactorings, targeted towards small scale use cases ("I want to
rename what is under my cursor", we actually have a prototype for this in
> Finally, the suggestion here:
> was not quite what I needed to use to correctly match the code used. The
> matcher I used was this:
> BindTemporaryExpression(has(Id("ctor", ConstructorCall()))),
> Id("operator", OverloadedOperatorCall()),
> Id("ctor", ConstructorCall()),
> Id("expr", Expression())
> So I had to add some extra BindTemporaryExpression() into the expression
> which I would have preferred to be automatic, like I think some implicit
> cast stuff is.
Yep, the temporary stuff is not yet perfect. Ideas welcome, preferably when
we have it in mainline ;) (there's a review thread currently open - afaik
nobody answered yet).
> Thanks for the guidance so far! :),
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the cfe-dev