LCOV - code coverage report
Current view: top level - clang/tools/extra/change-namespace - ChangeNamespace.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 2 2 100.0 %
Date: 2017-09-14 15:23:50 Functions: 1 2 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- ChangeNamespace.h -- Change namespace  ------------------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #ifndef LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H
      11             : #define LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H
      12             : 
      13             : #include "clang/ASTMatchers/ASTMatchFinder.h"
      14             : #include "clang/Format/Format.h"
      15             : #include "clang/Tooling/Core/Replacement.h"
      16             : #include "llvm/Support/Regex.h"
      17             : #include <string>
      18             : 
      19             : namespace clang {
      20             : namespace change_namespace {
      21             : 
      22             : // This tool can be used to change the surrounding namespaces of class/function
      23             : // definitions. Classes/functions in the moved namespace will have new
      24             : // namespaces while references to symbols (e.g. types, functions) which are not
      25             : // defined in the changed namespace will be correctly qualified by prepending
      26             : // namespace specifiers before them.
      27             : // This will try to add shortest namespace specifiers possible. When a symbol
      28             : // reference needs to be fully-qualified, this adds a "::" prefix to the
      29             : // namespace specifiers unless the new namespace is the global namespace.
      30             : // For classes, only classes that are declared/defined in the given namespace in
      31             : // speficifed files will be moved: forward declarations will remain in the old
      32             : // namespace.
      33             : // For example, changing "a" to "x":
      34             : // Old code:
      35             : //   namespace a {
      36             : //   class FWD;
      37             : //   class A { FWD *fwd; }
      38             : //   }  // a
      39             : // New code:
      40             : //   namespace a {
      41             : //   class FWD;
      42             : //   }  // a
      43             : //   namespace x {
      44             : //   class A { ::a::FWD *fwd; }
      45             : //   }  // x
      46             : // FIXME: support moving typedef, enums across namespaces.
      47         966 : class ChangeNamespaceTool : public ast_matchers::MatchFinder::MatchCallback {
      48             : public:
      49             :   // Moves code in the old namespace `OldNs` to the new namespace `NewNs` in
      50             :   // files matching `FilePattern`.
      51             :   ChangeNamespaceTool(
      52             :       llvm::StringRef OldNs, llvm::StringRef NewNs, llvm::StringRef FilePattern,
      53             :       llvm::ArrayRef<std::string> WhiteListedSymbolPatterns,
      54             :       std::map<std::string, tooling::Replacements> *FileToReplacements,
      55             :       llvm::StringRef FallbackStyle = "LLVM");
      56             : 
      57             :   void registerMatchers(ast_matchers::MatchFinder *Finder);
      58             : 
      59             :   void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
      60             : 
      61             :   // Moves the changed code in old namespaces but leaves class forward
      62             :   // declarations behind.
      63             :   void onEndOfTranslationUnit() override;
      64             : 
      65             : private:
      66             :   void moveOldNamespace(const ast_matchers::MatchFinder::MatchResult &Result,
      67             :                         const NamespaceDecl *NsDecl);
      68             : 
      69             :   void moveClassForwardDeclaration(
      70             :       const ast_matchers::MatchFinder::MatchResult &Result,
      71             :       const NamedDecl *FwdDecl);
      72             : 
      73             :   void replaceQualifiedSymbolInDeclContext(
      74             :       const ast_matchers::MatchFinder::MatchResult &Result,
      75             :       const DeclContext *DeclContext, SourceLocation Start, SourceLocation End,
      76             :       const NamedDecl *FromDecl);
      77             : 
      78             :   void fixTypeLoc(const ast_matchers::MatchFinder::MatchResult &Result,
      79             :                   SourceLocation Start, SourceLocation End, TypeLoc Type);
      80             : 
      81             :   void fixUsingShadowDecl(const ast_matchers::MatchFinder::MatchResult &Result,
      82             :                           const UsingDecl *UsingDeclaration);
      83             : 
      84             :   void fixDeclRefExpr(const ast_matchers::MatchFinder::MatchResult &Result,
      85             :                       const DeclContext *UseContext, const NamedDecl *From,
      86             :                       const DeclRefExpr *Ref);
      87             : 
      88             :   // Information about moving an old namespace.
      89             :   struct MoveNamespace {
      90             :     // The start offset of the namespace block being moved in the original
      91             :     // code.
      92             :     unsigned Offset;
      93             :     // The length of the namespace block in the original code.
      94             :     unsigned Length;
      95             :     // The offset at which the new namespace block will be inserted in the
      96             :     // original code.
      97             :     unsigned InsertionOffset;
      98             :     // The file in which the namespace is declared.
      99             :     FileID FID;
     100             :     SourceManager *SourceMgr;
     101             :   };
     102             : 
     103             :   // Information about inserting a class forward declaration.
     104          14 :   struct InsertForwardDeclaration {
     105             :     // The offset at while the forward declaration will be inserted in the
     106             :     // original code.
     107             :     unsigned InsertionOffset;
     108             :     // The code to be inserted.
     109             :     std::string ForwardDeclText;
     110             :   };
     111             : 
     112             :   std::string FallbackStyle;
     113             :   // In match callbacks, this contains replacements for replacing `typeLoc`s in
     114             :   // and deleting forward declarations in the moved namespace blocks.
     115             :   // In `onEndOfTranslationUnit` callback, the previous added replacements are
     116             :   // applied (on the moved namespace blocks), and then changed code in old
     117             :   // namespaces re moved to new namespaces, and previously deleted forward
     118             :   // declarations are inserted back to old namespaces, from which they are
     119             :   // deleted.
     120             :   std::map<std::string, tooling::Replacements> &FileToReplacements;
     121             :   // A fully qualified name of the old namespace without "::" prefix, e.g.
     122             :   // "a::b::c".
     123             :   std::string OldNamespace;
     124             :   // A fully qualified name of the new namespace without "::" prefix, e.g.
     125             :   // "x::y::z".
     126             :   std::string NewNamespace;
     127             :   // The longest suffix in the old namespace that does not overlap the new
     128             :   // namespace.
     129             :   // For example, if `OldNamespace` is "a::b::c" and `NewNamespace` is
     130             :   // "a::x::y", then `DiffOldNamespace` will be "b::c".
     131             :   std::string DiffOldNamespace;
     132             :   // The longest suffix in the new namespace that does not overlap the old
     133             :   // namespace.
     134             :   // For example, if `OldNamespace` is "a::b::c" and `NewNamespace` is
     135             :   // "a::x::y", then `DiffNewNamespace` will be "x::y".
     136             :   std::string DiffNewNamespace;
     137             :   // A regex pattern that matches files to be processed.
     138             :   std::string FilePattern;
     139             :   llvm::Regex FilePatternRE;
     140             :   // Information about moved namespaces grouped by file.
     141             :   // Since we are modifying code in old namespaces (e.g. add namespace
     142             :   // spedifiers) as well as moving them, we store information about namespaces
     143             :   // to be moved and only move them after all modifications are finished (i.e.
     144             :   // in `onEndOfTranslationUnit`).
     145             :   std::map<std::string, std::vector<MoveNamespace>> MoveNamespaces;
     146             :   // Information about forward declaration insertions grouped by files.
     147             :   // A class forward declaration is not moved, so it will be deleted from the
     148             :   // moved code block and inserted back into the old namespace. The insertion
     149             :   // will be done after removing the code from the old namespace and before
     150             :   // inserting it to the new namespace.
     151             :   std::map<std::string, std::vector<InsertForwardDeclaration>> InsertFwdDecls;
     152             :   // Records all using declarations, which can be used to shorten namespace
     153             :   // specifiers.
     154             :   llvm::SmallPtrSet<const UsingDecl *, 8> UsingDecls;
     155             :   // Records all using namespace declarations, which can be used to shorten
     156             :   // namespace specifiers.
     157             :   llvm::SmallPtrSet<const UsingDirectiveDecl *, 8> UsingNamespaceDecls;
     158             :   // Records all namespace alias declarations, which can be used to shorten
     159             :   // namespace specifiers.
     160             :   llvm::SmallPtrSet<const NamespaceAliasDecl *, 8> NamespaceAliasDecls;
     161             :   // TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
     162             :   // be fixed.
     163             :   llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
     164             :   // Since a DeclRefExpr for a function call can be matched twice (one as
     165             :   // CallExpr and one as DeclRefExpr), we record all DeclRefExpr's that have
     166             :   // been processed so that we don't handle them twice.
     167             :   llvm::SmallPtrSet<const clang::DeclRefExpr*, 16> ProcessedFuncRefs;
     168             :   // Patterns of symbol names whose references are not expected to be updated
     169             :   // when changing namespaces around them.
     170             :   std::vector<llvm::Regex> WhiteListedSymbolRegexes;
     171             : };
     172             : 
     173             : } // namespace change_namespace
     174             : } // namespace clang
     175             : 
     176             : #endif // LLVM_CLANG_TOOLS_EXTRA_CHANGE_NAMESPACE_CHANGENAMESPACE_H

Generated by: LCOV version 1.13