| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| //===-- tools/extra/clang-reorder-fields/tool/ClangReorderFields.cpp -*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| /// | ||
| /// \file | ||
| /// This file contains the implementation of clang-reorder-fields tool | ||
| /// | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "../ReorderFieldsAction.h" | ||
| #include "clang/Basic/Diagnostic.h" | ||
| #include "clang/Basic/DiagnosticOptions.h" | ||
| #include "clang/Basic/FileManager.h" | ||
| #include "clang/Basic/LangOptions.h" | ||
| #include "clang/Basic/SourceManager.h" | ||
| #include "clang/Frontend/TextDiagnosticPrinter.h" | ||
| #include "clang/Rewrite/Core/Rewriter.h" | ||
| #include "clang/Tooling/CommonOptionsParser.h" | ||
| #include "clang/Tooling/Refactoring.h" | ||
| #include "clang/Tooling/Tooling.h" | ||
| #include "llvm/ADT/IntrusiveRefCntPtr.h" | ||
| #include "llvm/Support/CommandLine.h" | ||
| #include "llvm/Support/FileSystem.h" | ||
| #include <cstdlib> | ||
| #include <string> | ||
| #include <system_error> | ||
|
|
||
| using namespace llvm; | ||
| using namespace clang; | ||
|
|
||
| cl::OptionCategory ClangReorderFieldsCategory("clang-reorder-fields options"); | ||
|
|
||
| static cl::opt<std::string> | ||
| RecordName("record-name", cl::Required, | ||
| cl::desc("The name of the struct/class."), | ||
| cl::cat(ClangReorderFieldsCategory)); | ||
|
|
||
| static cl::list<std::string> FieldsOrder("fields-order", cl::CommaSeparated, | ||
| cl::OneOrMore, | ||
| cl::desc("The desired fields order."), | ||
| cl::cat(ClangReorderFieldsCategory)); | ||
|
|
||
| static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited files."), | ||
| cl::cat(ClangReorderFieldsCategory)); | ||
|
|
||
| const char Usage[] = "A tool to reorder fields in C/C++ structs/classes.\n"; | ||
|
|
||
| int main(int argc, const char **argv) { | ||
| tooling::CommonOptionsParser OP(argc, argv, ClangReorderFieldsCategory, | ||
| Usage); | ||
|
|
||
| auto Files = OP.getSourcePathList(); | ||
| tooling::RefactoringTool Tool(OP.getCompilations(), Files); | ||
|
|
||
| reorder_fields::ReorderFieldsAction Action(RecordName, FieldsOrder, | ||
| Tool.getReplacements()); | ||
|
|
||
| auto Factory = tooling::newFrontendActionFactory(&Action); | ||
|
|
||
| if (Inplace) | ||
| return Tool.runAndSave(Factory.get()); | ||
|
|
||
| int ExitCode = Tool.run(Factory.get()); | ||
| LangOptions DefaultLangOptions; | ||
| IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions()); | ||
| TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); | ||
| DiagnosticsEngine Diagnostics( | ||
| IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, | ||
| &DiagnosticPrinter, false); | ||
|
|
||
| auto &FileMgr = Tool.getFiles(); | ||
| SourceManager Sources(Diagnostics, FileMgr); | ||
| Rewriter Rewrite(Sources, DefaultLangOptions); | ||
| Tool.applyAllReplacements(Rewrite); | ||
|
|
||
| for (const auto &File : Files) { | ||
| const auto *Entry = FileMgr.getFile(File); | ||
| const auto ID = Sources.translateFile(Entry); | ||
| // The method Rewriter::getRewriteBufferFor returns nullptr if | ||
| // the file has not been changed. | ||
| if (const auto *RB = Rewrite.getRewriteBufferFor(ID)) | ||
| RB->write(outs()); | ||
| else | ||
| outs() << Sources.getMemoryBufferForFile(Entry)->getBuffer(); | ||
| } | ||
|
|
||
| return ExitCode; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // RUN: clang-reorder-fields -record-name Foo -fields-order z,y,x %s -- | FileCheck %s | ||
|
|
||
| // The order of fields should not change. | ||
| class Foo { | ||
| public: | ||
| int x; // CHECK: {{^ int x;}} | ||
| int y; // CHECK-NEXT: {{^ int y;}} | ||
| int z; // CHECK-NEXT: {{^ int z;}} | ||
| }; | ||
|
|
||
| int main() { | ||
| Foo foo = { 0, 1 }; // CHECK: {{^ Foo foo = { 0, 1 };}} | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // RUN: clang-reorder-fields -record-name ::Foo -fields-order y,x %s -- | FileCheck %s | ||
|
|
||
| struct Foo { | ||
| int x; // CHECK: {{^ double y;}} | ||
| double y; // CHECK-NEXT: {{^ int x;}} | ||
| }; | ||
|
|
||
| namespace bar { | ||
| struct Foo { | ||
| int x; // CHECK: {{^ int x;}} | ||
| double y; // CHECK-NEXT: {{^ double y;}} | ||
| }; | ||
| } // end namespace bar | ||
|
|
||
| int main() { | ||
| bar::Foo foo = { 1, 1.7 }; // CHECK: {{^ bar::Foo foo = { 1, 1.7 };}} | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // RUN: clang-reorder-fields -record-name ::bar::Foo -fields-order z,w,y,x %s -- | FileCheck %s | ||
|
|
||
| namespace bar { | ||
| struct Foo { | ||
| const int* x; // CHECK: {{^ double z;}} | ||
| int y; // CHECK-NEXT: {{^ int w;}} | ||
| double z; // CHECK-NEXT: {{^ int y;}} | ||
| int w; // CHECK-NEXT: {{^ const int\* x}} | ||
| }; | ||
| } // end namespace bar | ||
|
|
||
| int main() { | ||
| const int x = 13; | ||
| bar::Foo foo = { &x, 0, 1.29, 17 }; // CHECK: {{^ bar::Foo foo = { 1.29, 17, 0, &x };}} | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // RUN: clang-reorder-fields -record-name Foo -fields-order z,y,x %s -- | FileCheck %s | ||
|
|
||
| // The order of fields should not change. | ||
| class Foo { | ||
| public: | ||
| int x; // CHECK: {{^ int x;}} | ||
|
|
||
| private: | ||
| int y; // CHECK: {{^ int y;}} | ||
| int z; // CHECK-NEXT: {{^ int z;}} | ||
| }; | ||
|
|
||
| int main() { | ||
| Foo foo; | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // RUN: clang-reorder-fields -record-name Foo -fields-order e,x,pi,s2,s1 %s -- -std=c++11 | FileCheck %s | ||
|
|
||
| class Foo { | ||
| public: | ||
| Foo(); | ||
|
|
||
| private: | ||
| int x; // CHECK: {{^ double e = 2.71;}} | ||
| const char *s1; // CHECK-NEXT: {{^ int x;}} | ||
| const char *s2; // CHECK-NEXT: {{^ double pi = 3.14;}} | ||
| double pi = 3.14; // CHECK-NEXT: {{^ const char \*s2;}} | ||
| double e = 2.71; // CHECK-NEXT: {{^ const char \*s1;}} | ||
| }; | ||
|
|
||
| Foo::Foo(): | ||
| x(12), // CHECK: {{^ x\(12\)}}, | ||
| s1("abc"), // CHECK-NEXT: {{^ s2\("def"\)}}, | ||
| s2("def") // CHECK-NEXT: {{^ s1\("abc"\)}} | ||
| {} | ||
|
|
||
| int main() { | ||
| Foo foo; | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // RUN: clang-reorder-fields -record-name Foo -fields-order s1,x,z,s2 %s -- | FileCheck %s | ||
|
|
||
| class Foo { | ||
| public: | ||
| Foo(); | ||
|
|
||
| private: | ||
| int x; // CHECK: {{^ const char \*s1;}} | ||
| const char *s1; // CHECK-NEXT: {{^ int x;}} | ||
| const char *s2; // CHECK-NEXT: {{^ double z;}} | ||
| double z; // CHECK-NEXT: {{^ const char \*s2;}} | ||
| }; | ||
|
|
||
| Foo::Foo(): | ||
| x(12), // CHECK: {{^ s1\("abc"\),}} | ||
| s1("abc"), // CHECK-NEXT: {{^ x\(12\),}} | ||
| s2("def"), // CHECK-NEXT: {{^ z\(3.14\),}} | ||
| z(3.14) // CHECK-NEXT: {{^ s2\("def"\)}} | ||
| {} | ||
|
|
||
| int main() { | ||
| Foo foo; | ||
| return 0; | ||
| } |