• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- CompilationDatabase.cpp - ----------------------------------------===//
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 //  This file contains implementations of the CompilationDatabase base class
11 //  and the FixedCompilationDatabase.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include <sstream>
16 #include "clang/Tooling/CompilationDatabase.h"
17 #include "clang/Tooling/CompilationDatabasePluginRegistry.h"
18 #include "clang/Tooling/Tooling.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/system_error.h"
22 
23 namespace clang {
24 namespace tooling {
25 
~CompilationDatabase()26 CompilationDatabase::~CompilationDatabase() {}
27 
28 CompilationDatabase *
loadFromDirectory(StringRef BuildDirectory,std::string & ErrorMessage)29 CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
30                                        std::string &ErrorMessage) {
31   std::stringstream ErrorStream;
32   for (CompilationDatabasePluginRegistry::iterator
33        It = CompilationDatabasePluginRegistry::begin(),
34        Ie = CompilationDatabasePluginRegistry::end();
35        It != Ie; ++It) {
36     std::string DatabaseErrorMessage;
37     OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate());
38     if (CompilationDatabase *DB =
39         Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
40       return DB;
41     else
42       ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
43   }
44   ErrorMessage = ErrorStream.str();
45   return NULL;
46 }
47 
48 static CompilationDatabase *
findCompilationDatabaseFromDirectory(StringRef Directory,std::string & ErrorMessage)49 findCompilationDatabaseFromDirectory(StringRef Directory,
50                                      std::string &ErrorMessage) {
51   std::stringstream ErrorStream;
52   while (!Directory.empty()) {
53     std::string LoadErrorMessage;
54 
55     if (CompilationDatabase *DB =
56            CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
57       return DB;
58     ErrorStream << "No compilation database found in " << Directory.str()
59                 << "\n" << LoadErrorMessage;
60 
61     Directory = llvm::sys::path::parent_path(Directory);
62   }
63   ErrorMessage = ErrorStream.str();
64   return NULL;
65 }
66 
67 CompilationDatabase *
autoDetectFromSource(StringRef SourceFile,std::string & ErrorMessage)68 CompilationDatabase::autoDetectFromSource(StringRef SourceFile,
69                                           std::string &ErrorMessage) {
70   llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
71   StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
72 
73   CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory,
74                                                                  ErrorMessage);
75 
76   if (!DB)
77     ErrorMessage = ("Could not auto-detect compilation database for file \"" +
78                    SourceFile + "\"\n" + ErrorMessage).str();
79   return DB;
80 }
81 
82 CompilationDatabase *
autoDetectFromDirectory(StringRef SourceDir,std::string & ErrorMessage)83 CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
84                                              std::string &ErrorMessage) {
85   llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
86 
87   CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath,
88                                                                  ErrorMessage);
89 
90   if (!DB)
91     ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
92                    SourceDir + "\"\n" + ErrorMessage).str();
93   return DB;
94 }
95 
~CompilationDatabasePlugin()96 CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
97 
98 FixedCompilationDatabase *
loadFromCommandLine(int & Argc,const char ** Argv,Twine Directory)99 FixedCompilationDatabase::loadFromCommandLine(int &Argc,
100                                               const char **Argv,
101                                               Twine Directory) {
102   const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
103   if (DoubleDash == Argv + Argc)
104     return NULL;
105   std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc);
106   Argc = DoubleDash - Argv;
107   return new FixedCompilationDatabase(Directory, CommandLine);
108 }
109 
110 FixedCompilationDatabase::
FixedCompilationDatabase(Twine Directory,ArrayRef<std::string> CommandLine)111 FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
112   std::vector<std::string> ToolCommandLine(1, "clang-tool");
113   ToolCommandLine.insert(ToolCommandLine.end(),
114                          CommandLine.begin(), CommandLine.end());
115   CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine));
116 }
117 
118 std::vector<CompileCommand>
getCompileCommands(StringRef FilePath) const119 FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
120   std::vector<CompileCommand> Result(CompileCommands);
121   Result[0].CommandLine.push_back(FilePath);
122   return Result;
123 }
124 
125 std::vector<std::string>
getAllFiles() const126 FixedCompilationDatabase::getAllFiles() const {
127   return std::vector<std::string>();
128 }
129 
130 // This anchor is used to force the linker to link in the generated object file
131 // and thus register the JSONCompilationDatabasePlugin.
132 extern volatile int JSONAnchorSource;
133 static int JSONAnchorDest = JSONAnchorSource;
134 
135 } // end namespace tooling
136 } // end namespace clang
137