315 lines · plain
1======================2Clang-Change-Namespace3======================4 5.. contents::6 7.. toctree::8 :maxdepth: 19 10:program:`clang-change-namespace` can be used to change the surrounding11namespaces of class/function definitions.12 13Classes/functions in the moved namespace will have new namespaces while14references to symbols (e.g. types, functions) which are not defined in the15changed namespace will be correctly qualified by prepending namespace specifiers16before them. This will try to add shortest namespace specifiers possible.17 18When a symbol reference needs to be fully-qualified, this adds a `::` prefix to19the namespace specifiers unless the new namespace is the global namespace. For20classes, only classes that are declared/defined in the given namespace in21specified files will be moved: forward declarations will remain in the old22namespace. The will be demonstrated in the next example.23 24Example usage25-------------26 27For example, consider this `test.cc` example here with the forward declared28class `FWD` and the defined class `A`, both in the namespace `a`.29 30.. code-block:: c++31 32 namespace a {33 class FWD;34 class A {35 FWD *fwd;36 };37 } // namespace a38 39And now let's change the namespace `a` to `x`.40 41.. code-block:: console42 43 clang-change-namespace \44 --old_namespace "a" \45 --new_namespace "x" \46 --file_pattern "test.cc" \47 --i \48 test.cc49 50Note that in the code below there's still the forward decalred class `FWD` that51stayed in the namespace `a`. It wasn't moved to the new namespace because it52wasn't defined/declared here in `a` but only forward declared.53 54.. code-block:: c++55 56 namespace a {57 class FWD;58 } // namespace a59 namespace x {60 61 class A {62 a::FWD *fwd;63 };64 } // namespace x65 66 67Another example68---------------69 70Consider this `test.cc` file:71 72.. code-block:: c++73 74 namespace na {75 class X {};76 namespace nb {77 class Y {78 X x;79 };80 } // namespace nb81 } // namespace na82 83To move the definition of class `Y` from namespace `na::nb` to `x::y`, run:84 85.. code-block:: console86 87 clang-change-namespace \88 --old_namespace "na::nb" \89 --new_namespace "x::y" \90 --file_pattern "test.cc" \91 --i \92 test.cc93 94This will overwrite `test.cc` to look like this:95 96.. code-block:: c++97 98 namespace na {99 class X {};100 101 } // namespace na102 namespace x {103 namespace y {104 class Y {105 na::X x;106 };107 } // namespace y108 } // namespace x109 110Note, that we've successfully moved the class `Y` from namespace `na::nb` to111namespace `x::y`.112 113Caveats114=======115 116Content already exists in new namespace117---------------------------------------118 119Consider this `test.cc` example that defines two `class A` one inside the120namespace `a` and one in namespace `b`:121 122.. code-block:: c++123 124 namespace a {125 class A {126 int classAFromWithinNamespace_a;127 };128 } // namespace a129 130 namespace b {131 class A {132 int classAFromWithinNamespace_b;133 };134 } //namespace b135 136Let's move everything from namespace `a` to namespace `b`:137 138.. code-block:: console139 140 clang-change-namespace \141 --old_namespace "a" \142 --new_namespace "b" \143 --file_pattern test.cc \144 test.cc145 146As expected we now have to definitions of `class A` inside the namespace `b`:147 148.. code-block:: c++149 150 namespace b {151 class A {152 int classAFromWithinNamespace_a;153 };154 } // namespace b155 156 namespace b {157 class A {158 int classAFromWithinNamespace_b;159 };160 } //namespace b161 162The re-factoring looks correct but the code will not compile due to the name163duplication. It is not up to the tool to ensure compilability in that sense.164But one has to be aware of that.165 166Inline namespace doesn't work167-----------------------------168 169Consider this usage of two versions of implementations for a `greet` function:170 171.. code-block:: c++172 173 #include <cstdio>174 175 namespace Greeter {176 inline namespace Version1 {177 const char* greet() { return "Hello from version 1!"; }178 } // namespace Version1179 namespace Version2 {180 const char* greet() { return "Hello from version 2!"; }181 } // namespace Version2182 } // namespace Greeter183 184 int main(int argc, char* argv[]) {185 printf("%s\n", Greeter::greet());186 return 0;187 }188 189Note, that currently `Greeter::greet()` will result in a call to190`Greeter::Version1::greet()` because that's the inlined namespace.191 192Let's say you want to move one and make `Version2` the default now and remove193the `inline` from the `Version1`. First let's try to turn `namespace Version2`194into `inline namespace Version2`:195 196.. code-block:: console197 198 clang-change-namespace \199 --old_namespace "Greeter::Version2" \200 --new_namespace "inline Version2" \201 --file_pattern main.cc main.cc202 203But this will put the `inline` keyword in the wrong place resulting in:204 205.. code-block:: c++206 207 #include <cstdio>208 209 namespace Greeter {210 inline namespace Version1 {211 const char* greet() { return "Hello from version 1!"; }212 } // namespace Version1213 214 } // namespace Greeter215 namespace inline Greeter {216 namespace Version2 {217 const char *greet() { return "Hello from version 2!"; }218 } // namespace Version2219 } // namespace inline Greeter220 221 int main(int argc, char* argv[]) {222 printf("%s\n", Greeter::greet());223 return 0;224 }225 226One cannot use `:program:`clang-change-namespace` to inline a namespace.227 228Symbol references not updated229-----------------------------230 231Consider this `test.cc` file:232 233.. code-block:: c++234 235 namespace old {236 struct foo {};237 } // namespace old238 239 namespace b {240 old::foo g_foo;241 } // namespace b242 243Notice that namespace `b` defines a global variable of type `old::foo`. If we244now change the name of the `old` namespace to `modern`, the reference will not245be updated:246 247.. code-block:: console248 249 clang-change-namespace \250 --old_namespace "old" \251 --new_namespace "modern" \252 --file_pattern test.cc \253 test.cc254 255.. code-block:: c++256 257 namespace modern {258 struct foo {};259 } // namespace modern260 261 namespace b {262 old::foo g_foo;263 } // namespace b264 265`g_foo` is still of the no longer existing type `old::foo` while instead it266should use `modern::foo`.267 268Only symbol references in the moved namespace are updated, not outside of it.269 270 271:program:`clang-change-namespace` Command Line Options272======================================================273 274.. option:: --allowed_file=<string>275 276 A file containing regexes of symbol names that are not expected to be updated277 when changing namespaces around them.278 279.. option:: --dump_result280 281 Dump new file contents in YAML, if specified.282 283.. option:: --extra-arg=<string>284 285 Additional argument to append to the compiler command line286 287.. option:: --extra-arg-before=<string>288 289 Additional argument to prepend to the compiler command line290 291.. option:: --file_pattern=<string>292 293 Only rename namespaces in files that match the given regular expression294 pattern.295 296.. option:: -i297 298 Inplace edit <file>s, if specified.299 300.. option:: --new_namespace=<string>301 302 New namespace. Use `""` when you target the global namespace.303 304.. option:: --old_namespace=<string>305 306 Old namespace.307 308.. option:: -p <string>309 310 Build path311 312.. option:: --style=<string>313 314 The style name used for reformatting.315