CompilationDatabase.cpp revision 245431
1234287Sdim//===--- CompilationDatabase.cpp - ----------------------------------------===//
2234287Sdim//
3234287Sdim//                     The LLVM Compiler Infrastructure
4234287Sdim//
5234287Sdim// This file is distributed under the University of Illinois Open Source
6234287Sdim// License. See LICENSE.TXT for details.
7234287Sdim//
8234287Sdim//===----------------------------------------------------------------------===//
9234287Sdim//
10245431Sdim//  This file contains implementations of the CompilationDatabase base class
11245431Sdim//  and the FixedCompilationDatabase.
12234287Sdim//
13234287Sdim//===----------------------------------------------------------------------===//
14234287Sdim
15245431Sdim#include <sstream>
16234287Sdim#include "clang/Tooling/CompilationDatabase.h"
17245431Sdim#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
18245431Sdim#include "clang/Tooling/Tooling.h"
19234287Sdim#include "llvm/ADT/SmallString.h"
20234287Sdim#include "llvm/Support/Path.h"
21234287Sdim#include "llvm/Support/system_error.h"
22234287Sdim
23234287Sdimnamespace clang {
24234287Sdimnamespace tooling {
25234287Sdim
26245431SdimCompilationDatabase::~CompilationDatabase() {}
27234287Sdim
28245431SdimCompilationDatabase *
29245431SdimCompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
30245431Sdim                                       std::string &ErrorMessage) {
31245431Sdim  std::stringstream ErrorStream;
32245431Sdim  for (CompilationDatabasePluginRegistry::iterator
33245431Sdim       It = CompilationDatabasePluginRegistry::begin(),
34245431Sdim       Ie = CompilationDatabasePluginRegistry::end();
35245431Sdim       It != Ie; ++It) {
36245431Sdim    std::string DatabaseErrorMessage;
37245431Sdim    OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate());
38245431Sdim    if (CompilationDatabase *DB =
39245431Sdim        Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
40245431Sdim      return DB;
41245431Sdim    else
42245431Sdim      ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
43234287Sdim  }
44245431Sdim  ErrorMessage = ErrorStream.str();
45245431Sdim  return NULL;
46245431Sdim}
47234287Sdim
48245431Sdimstatic CompilationDatabase *
49245431SdimfindCompilationDatabaseFromDirectory(StringRef Directory,
50245431Sdim                                     std::string &ErrorMessage) {
51245431Sdim  std::stringstream ErrorStream;
52245431Sdim  bool HasErrorMessage = false;
53245431Sdim  while (!Directory.empty()) {
54245431Sdim    std::string LoadErrorMessage;
55234287Sdim
56245431Sdim    if (CompilationDatabase *DB =
57245431Sdim           CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
58245431Sdim      return DB;
59234287Sdim
60245431Sdim    if (!HasErrorMessage) {
61245431Sdim      ErrorStream << "No compilation database found in " << Directory.str()
62245431Sdim                  << " or any parent directory\n" << LoadErrorMessage;
63245431Sdim      HasErrorMessage = true;
64234287Sdim    }
65234287Sdim
66245431Sdim    Directory = llvm::sys::path::parent_path(Directory);
67234287Sdim  }
68245431Sdim  ErrorMessage = ErrorStream.str();
69245431Sdim  return NULL;
70245431Sdim}
71234287Sdim
72245431SdimCompilationDatabase *
73245431SdimCompilationDatabase::autoDetectFromSource(StringRef SourceFile,
74245431Sdim                                          std::string &ErrorMessage) {
75245431Sdim  llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
76245431Sdim  StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
77234287Sdim
78245431Sdim  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory,
79245431Sdim                                                                 ErrorMessage);
80234287Sdim
81245431Sdim  if (!DB)
82245431Sdim    ErrorMessage = ("Could not auto-detect compilation database for file \"" +
83245431Sdim                   SourceFile + "\"\n" + ErrorMessage).str();
84245431Sdim  return DB;
85234287Sdim}
86234287Sdim
87245431SdimCompilationDatabase *
88245431SdimCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
89245431Sdim                                             std::string &ErrorMessage) {
90245431Sdim  llvm::SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
91234287Sdim
92245431Sdim  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath,
93245431Sdim                                                                 ErrorMessage);
94234287Sdim
95245431Sdim  if (!DB)
96245431Sdim    ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
97245431Sdim                   SourceDir + "\"\n" + ErrorMessage).str();
98245431Sdim  return DB;
99234287Sdim}
100234287Sdim
101245431SdimCompilationDatabasePlugin::~CompilationDatabasePlugin() {}
102245431Sdim
103235633SdimFixedCompilationDatabase *
104235633SdimFixedCompilationDatabase::loadFromCommandLine(int &Argc,
105235633Sdim                                              const char **Argv,
106235633Sdim                                              Twine Directory) {
107235633Sdim  const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
108235633Sdim  if (DoubleDash == Argv + Argc)
109235633Sdim    return NULL;
110235633Sdim  std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc);
111235633Sdim  Argc = DoubleDash - Argv;
112235633Sdim  return new FixedCompilationDatabase(Directory, CommandLine);
113235633Sdim}
114235633Sdim
115235633SdimFixedCompilationDatabase::
116235633SdimFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
117235633Sdim  std::vector<std::string> ToolCommandLine(1, "clang-tool");
118235633Sdim  ToolCommandLine.insert(ToolCommandLine.end(),
119235633Sdim                         CommandLine.begin(), CommandLine.end());
120235633Sdim  CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine));
121235633Sdim}
122235633Sdim
123235633Sdimstd::vector<CompileCommand>
124235633SdimFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
125235633Sdim  std::vector<CompileCommand> Result(CompileCommands);
126235633Sdim  Result[0].CommandLine.push_back(FilePath);
127235633Sdim  return Result;
128235633Sdim}
129235633Sdim
130245431Sdimstd::vector<std::string>
131245431SdimFixedCompilationDatabase::getAllFiles() const {
132245431Sdim  return std::vector<std::string>();
133234287Sdim}
134234287Sdim
135245431Sdim// This anchor is used to force the linker to link in the generated object file
136245431Sdim// and thus register the JSONCompilationDatabasePlugin.
137245431Sdimextern volatile int JSONAnchorSource;
138245431Sdimstatic int JSONAnchorDest = JSONAnchorSource;
139234287Sdim
140234287Sdim} // end namespace tooling
141234287Sdim} // end namespace clang
142