Author: ioeric Date: Wed Oct 12 07:34:18 2016 New Revision: 284011 URL: http://llvm.org/viewvc/llvm-project?rev=284011&view=rev Log: [change-namespace] don't miss comments in the beginning of a namespace block.
Reviewers: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D25397 Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp?rev=284011&r1=284010&r2=284011&view=diff ============================================================================== --- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original) +++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Wed Oct 12 07:34:18 2016 @@ -82,33 +82,42 @@ const NamespaceDecl *getOuterNamespace(c return CurrentNs; } -// FIXME: get rid of this helper function if this is supported in clang-refactor -// library. -SourceLocation getStartOfNextLine(SourceLocation Loc, const SourceManager &SM, - const LangOptions &LangOpts) { +static std::unique_ptr<Lexer> +getLexerStartingFromLoc(SourceLocation Loc, const SourceManager &SM, + const LangOptions &LangOpts) { if (Loc.isMacroID() && !Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc)) - return SourceLocation(); + return nullptr; // Break down the source location. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); // Try to load the file buffer. bool InvalidTemp = false; llvm::StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp); if (InvalidTemp) - return SourceLocation(); + return nullptr; const char *TokBegin = File.data() + LocInfo.second; // Lex from the start of the given location. - Lexer Lex(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(), - TokBegin, File.end()); + return llvm::make_unique<Lexer>(SM.getLocForStartOfFile(LocInfo.first), + LangOpts, File.begin(), TokBegin, File.end()); +} +// FIXME: get rid of this helper function if this is supported in clang-refactor +// library. +static SourceLocation getStartOfNextLine(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts) { + std::unique_ptr<Lexer> Lex = getLexerStartingFromLoc(Loc, SM, LangOpts); + if (!Lex.get()) + return SourceLocation(); llvm::SmallVector<char, 16> Line; // FIXME: this is a bit hacky to get ReadToEndOfLine work. - Lex.setParsingPreprocessorDirective(true); - Lex.ReadToEndOfLine(&Line); + Lex->setParsingPreprocessorDirective(true); + Lex->ReadToEndOfLine(&Line); auto End = Loc.getLocWithOffset(Line.size()); - return SM.getLocForEndOfFile(LocInfo.first) == End ? End - : End.getLocWithOffset(1); + return SM.getLocForEndOfFile(SM.getDecomposedLoc(Loc).first) == End + ? End + : End.getLocWithOffset(1); } // Returns `R` with new range that refers to code after `Replaces` being @@ -365,6 +374,23 @@ void ChangeNamespaceTool::run( } } +static SourceLocation getLocAfterNamespaceLBrace(const NamespaceDecl *NsDecl, + const SourceManager &SM, + const LangOptions &LangOpts) { + std::unique_ptr<Lexer> Lex = + getLexerStartingFromLoc(NsDecl->getLocStart(), SM, LangOpts); + assert(Lex.get() && + "Failed to create lexer from the beginning of namespace."); + if (!Lex.get()) + return SourceLocation(); + Token Tok; + while (!Lex->LexFromRawLexer(Tok) && Tok.isNot(tok::TokenKind::l_brace)) { + } + return Tok.isNot(tok::TokenKind::l_brace) + ? SourceLocation() + : Tok.getEndLoc().getLocWithOffset(1); +} + // Stores information about a moved namespace in `MoveNamespaces` and leaves // the actual movement to `onEndOfTranslationUnit()`. void ChangeNamespaceTool::moveOldNamespace( @@ -375,7 +401,9 @@ void ChangeNamespaceTool::moveOldNamespa return; // Get the range of the code in the old namespace. - SourceLocation Start = NsDecl->decls_begin()->getLocStart(); + SourceLocation Start = getLocAfterNamespaceLBrace( + NsDecl, *Result.SourceManager, Result.Context->getLangOpts()); + assert(Start.isValid() && "Can't find l_brace for namespace."); SourceLocation End = NsDecl->getRBraceLoc().getLocWithOffset(-1); // Create a replacement that deletes the code in the old namespace merely for // retrieving offset and length from it. Modified: clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp?rev=284011&r1=284010&r2=284011&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp (original) +++ clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp Wed Oct 12 07:34:18 2016 @@ -552,6 +552,38 @@ TEST_F(ChangeNamespaceTest, NoMisplaceAt EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } +TEST_F(ChangeNamespaceTest, CommentsBeforeMovedClass) { + std::string Code = "namespace na {\n" + "namespace nb {\n" + "\n\n" + "// Wild comments.\n" + "\n" + "// Comments.\n" + "// More comments.\n" + "class B {\n" + " // Private comments.\n" + " int a;\n" + "};\n" + "}\n" + "}"; + std::string Expected = "\n" + "\n" + "namespace x {\n" + "namespace y {\n" + "\n\n" + "// Wild comments.\n" + "\n" + "// Comments.\n" + "// More comments.\n" + "class B {\n" + " // Private comments.\n" + " int a;\n" + "};\n" + "} // namespace y\n" + "} // namespace x\n"; + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); +} + } // anonymous namespace } // namespace change_namespace } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits