Range of getTypeSourceInfo for VarDecl

Hello,

I'd like to rewrite a variable declaration such as "unsigned int x" to
"BAR<unsigned int> x". For this, I've had a peak at the auto rewriter
and I managed to get the simpler case "int x" to work just fine. But
for types such as "unsigned int x" it won't work (it will rewrite to
"BAR<unsigned> int x").

The current code looks as follows where Result is of type
MatchFinder::MatchResult:

  const VarDecl *V = ...
  SourceLocation Loc = V->getLocation();
  SourceManager &SM = *Result.SourceManager;
  TypeLoc TL = V->getTypeSourceInfo()->getTypeLoc();

  // Likely problematic ...
  SourceRange SR = TL.getSourceRange();
  CharSourceRange Range = Lexer::makeFileCharRange(
      CharSourceRange::getTokenRange(SR), SM, LO);

  const LangOptions& LO = Result.Context->getLangOpts();

  Replace.insert(tooling::Replacement(SM, Range.getBegin(), 0, "Bar<"));
  Replace.insert(tooling::Replacement(SM, Range.getEnd(), 0, ">"));

As indicated, the problem has likely to do with a wrong assumption
about the lexemes. I've tried various things to avoid the Lexer
including using V->getSourceRange() and V->getType().getAsString()
instead. This works OK for cases like "int x" and the seemingly more
complicated case "unsigned int x" but it breaks for declarations with
initializers, e.g. "unsigned int x = 42".

It almost would seem as if it is preferable to use
V->getType().getAsString() to handle cases such as "int y[5]" which
should be rewritten to "BAR<int [5]> y". But I would be already happy
if I would get the "unsigned int x" case to work before considering
more complicated cases.

Any hints on how one might go about rewriting these kind of variable
declarations would be much appreciated.

With kind regards,
Alex

Hello,

I'd like to rewrite a variable declaration such as "unsigned int x" to
"BAR<unsigned int> x". For this, I've had a peak at the auto rewriter
and I managed to get the simpler case "int x" to work just fine. But
for types such as "unsigned int x" it won't work (it will rewrite to
"BAR<unsigned> int x").

This looks like it might be the old "token vs. location" problem (source
ranges point to tokens, and if given a token, the Replacement assumes
"start of token"). Usually you need to say Lexer::MeasureTokenLength to get
past the end of the token. See
http://reviews.llvm.org/diffusion/L/browse/cfe/trunk/lib/Tooling/Refactoring.cpp;212403$125
for how it's used. Or you go forward to find the next token (either with
the lexer, or by pulling out the first vardecl).

The current code looks as follows where Result is of type
MatchFinder::MatchResult:

  const VarDecl *V = ...
  SourceLocation Loc = V->getLocation();
  SourceManager &SM = *Result.SourceManager;
  TypeLoc TL = V->getTypeSourceInfo()->getTypeLoc();

  // Likely problematic ...
  SourceRange SR = TL.getSourceRange();
  CharSourceRange Range = Lexer::makeFileCharRange(
      CharSourceRange::getTokenRange(SR), SM, LO);

Why do you need the lexer? Won't CharSourceRange::getTokenRange(SR) do what
you want?

  const LangOptions& LO = Result.Context->getLangOpts();

  Replace.insert(tooling::Replacement(SM, Range.getBegin(), 0, "Bar<"));
  Replace.insert(tooling::Replacement(SM, Range.getEnd(), 0, ">"));

Otherwise this looks about right.