Clang tutorial
Milian Wolff
mail at milianw.de
Sun Feb 9 14:48:05 UTC 2014
Hey all,
I'm forwarding this to kdevelop-devel at kde.org - please direct the future
replies there so others can read it too and chime in if desired.
On Saturday 08 February 2014 16:47:14 Michael Ferris wrote:
> Hi, my name is Michael, we haven't met yet, but I am one the guys that will
> be working on Clang for kDevelop for the next weeks.
>
> We have started working on it a bit. So far we enabled renaming of
> variables, however, since this is not language dependant, we only needed to
> hook the refactor menu to the basic refactor component which uses the
> DUChain to do the renaming.
Cool, is the patch already up for review? I might have missed it so far.
Otherwise, push it to reviewboard and I'll have a look.
> Now, that said, we would like to know how to start using Clang.
>
> If we start from clanglanguagesupport.cpp, what are the links with clang
> that we can use to read/modify the code ?
Using the existing language-agnostic framework is perfectly fine for some
features like the above. For other parts leveraging clang instead might be
better, but thats left to be seen and decided on a case-by-case study.
> Also, if you could give us a quick overview of the main components of clang
> and their relations to one another and the current code, that would be most
> appreciated.
So, from clang itself we only use the clang-c API, see esp.
/usr/include/clang-c/Index.h
This is used mostly in two places so far:
#1 - the DUChain integration.
The DUChain in KDevplatform is a strange name for what basically is a cache of
data from language plugins. It holds locations and types of declarations,
contexts, uses, ...
In the kdev-clang/duchain folder, you'll see our current approach in
translating the data we get from clang-c into the existing data structures of
the DUChain. The ClangParseJob is run for every file you edit or which is part
of a project loaded in KDevelop. There a ParseSession is created which
builds/updates a clang translation unit. This is then run through the
TUDUChain builder which extracts the contexts, declarations, types and uses
out of the TU and stores them in the serializable data structures of the
DUChain.
Once we have that done, stuff like context browsing and code highlighting are
extracted from these data automatically by code in KDevPlatform.
If you spot any bugs there, such as wrong types in a context browser popup, or
bad code highlighting, you'll want to touch this part. Otherwise, this is
mostly done I think and not so much is left to do. Some things I can think of
are:
## Forward Declarations
Afaik, we don't special-case forward declarations at all so far. This could be
useful, to get the nicer navigation popups which offer you to jump to the
"actual" declaration etc.
## Qt Integration
This is probably pretty hard, but our existing C++ plugin has some special
code for improved Qt support. Qt uses the moc, a pre-preprocessor for some
special code generation and the actual compiler won't see most of the
"special" macros. Olivier Goffart did some investigations in that regard
though, and showed that clang can be made to work with this, see
http://woboq.com/blog/moc-with-clang.html . It's left to be seen how we can
achieve the same and whether that data is then also accessible for us via the
clang-c API. Without that, support for signals/slots and other core Qt
features will suffer.
#2 - Code Completion
This is in the kdev-clang/codecompletion folder, mostly see context.cpp
therein. Given a cached ParseSession from a previous ClangParseJob run, we
invoke the respective clang-c API to get code completion results. The output
is then again translated into KDevelop-specific data structures. This is so
far quite minimalistic but works reasonably well for the simple code
completion.
Here, quite a few things can and should be done by you guys I hope. Mostly,
this is implementing features we have in our current C++ KDevelop plugin, but
which are not provided by the clang API as of yet. Here's a list of things
that are missing:
## Implement Function
If a function is only declared but not defined, we offer a "implement
function" helper item in the code completion. Try it out in our old C++
plugin:
class foo { void bar(int i); };
// invoke code completion here
You'll see a "implement foo::bar" code completion item which when executed
inserts the boilerplate code:
void foo::bar(int i)
{
}
This should be done in kdev-clang as well. So, investigate how to get this
information from clang-c or based on our DUChain data, and copy/reimplement
the feature from kdevelop/languages/cpp/. See esp. the
ImplementationHelperItem.
## Override Function
Invoking code completion in a class body which inherits from a polymorphic
class, add items which offer you to override a virtual function of a base
class. Here, its left to be seen how to implement it, i.e. based on the
DUChain or whether clang offers this information to us. This feature is
implemented also in the ImplementationHelperItem in our existing cpp plugin.
## Missing Includes
When you try to access a class or function in a file but have not yet added
the respective include statement for the header which declares it, KDevelop
should offer you to insert the missing include. See the files with that name
in kdevelop/languages/cpp. This probably is mostly copy'n'pasting of the code
(and cleaning it up), as finding the files cannot be done by clang, but only
via our DUChain cache.
## Call Tips
When showing code completion inside a function call or constructor, we want to
show information about the functions that can be called. I.e. what functions
are viable for the previously written arguments, what overloads exist and what
their signatures are.
This is probably all thats missing from code completion so far. Did I forget
anything?
#3 - Assistants / Refactoring
Another neat feature in KDevelop which we want to have also in kdev-clang, are
the assistants. See also kdevelop/languages/cpp/codegen/
## Rename
When you change the name of a local variable declaration, which was used
somewhere, we offer an assistant which can be invoked by "Alt + 1" - this then
triggers a rename of all uses of the old variable.
## Adapt Signature
Similar to the above, if you change the signature of a function
declaration/definition, we offer you to adapt the corresponding
definition/declaration signature.
## Declare function/member/variable
When you use some undeclared function/member/variable, we offer you to create
a private/public/local declaration of that as appropriate.
## Rename File
When you rename a class and the file it was declared in matches the old
identifier, we offer you to rename the file in accordance.
## $neat feature
Afaik, clang comes with a lot of interesting refactoring tools. It would be
cool to integrate them somehow.
#4 - Other Stuff
Another feature which is currently missing, is special support for macros. See
our old's cpplanguagesupport.cpp and the specialLanguageObject* code in there.
It adds code browsing support when the cursor is inside a macro expansion and
shows the macro, its definition and the actual expanded preprocessed text.
Would be cool if we can keep that somehow when we get that info from clang.
See also cppduchain/navigation/ - esp. the includenavigation* and
macronavigation* files.
#5 - Clang Format
Unrelated to the actual language support plugin, is adding a code formatter
which uses clang-format.
#6 - tl;dr;
So, this was a long mail but I hope this gives you some ideas on what you can
work on. Generally, pick what fits you best and whats interesting to you. Try
to use our old C++ plugin for some of the features above to see how they
should work. If you have other nice ideas for what to do, go for it! If you
have any problems, ask on our mailing list!
Bye and have fun!
--
Milian Wolff
mail at milianw.de
http://milianw.de
More information about the KDevelop-devel
mailing list