CompilationDatabase.cpp revision 252723
1219820Sjeff//===--- CompilationDatabase.cpp - ----------------------------------------===//
2219820Sjeff//
3219820Sjeff//                     The LLVM Compiler Infrastructure
4219820Sjeff//
5219820Sjeff// This file is distributed under the University of Illinois Open Source
6219820Sjeff// License. See LICENSE.TXT for details.
7219820Sjeff//
8219820Sjeff//===----------------------------------------------------------------------===//
9219820Sjeff//
10219820Sjeff//  This file contains implementations of the CompilationDatabase base class
11219820Sjeff//  and the FixedCompilationDatabase.
12219820Sjeff//
13219820Sjeff//===----------------------------------------------------------------------===//
14219820Sjeff
15219820Sjeff#include "clang/Tooling/CompilationDatabase.h"
16219820Sjeff#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
17219820Sjeff#include "clang/Tooling/Tooling.h"
18219820Sjeff#include "llvm/ADT/SmallString.h"
19219820Sjeff#include "llvm/Support/Path.h"
20219820Sjeff#include "llvm/Support/system_error.h"
21219820Sjeff#include <sstream>
22219820Sjeff
23219820Sjeffnamespace clang {
24219820Sjeffnamespace tooling {
25219820Sjeff
26219820SjeffCompilationDatabase::~CompilationDatabase() {}
27219820Sjeff
28219820SjeffCompilationDatabase *
29219820SjeffCompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
30219820Sjeff                                       std::string &ErrorMessage) {
31219820Sjeff  std::stringstream ErrorStream;
32219820Sjeff  for (CompilationDatabasePluginRegistry::iterator
33219820Sjeff       It = CompilationDatabasePluginRegistry::begin(),
34219820Sjeff       Ie = CompilationDatabasePluginRegistry::end();
35219820Sjeff       It != Ie; ++It) {
36219820Sjeff    std::string DatabaseErrorMessage;
37219820Sjeff    OwningPtr<CompilationDatabasePlugin> Plugin(It->instantiate());
38219820Sjeff    if (CompilationDatabase *DB =
39219820Sjeff        Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
40219820Sjeff      return DB;
41219820Sjeff    else
42219820Sjeff      ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
43219820Sjeff  }
44219820Sjeff  ErrorMessage = ErrorStream.str();
45219820Sjeff  return NULL;
46219820Sjeff}
47219820Sjeff
48219820Sjeffstatic CompilationDatabase *
49219820SjefffindCompilationDatabaseFromDirectory(StringRef Directory,
50219820Sjeff                                     std::string &ErrorMessage) {
51219820Sjeff  std::stringstream ErrorStream;
52219820Sjeff  bool HasErrorMessage = false;
53219820Sjeff  while (!Directory.empty()) {
54219820Sjeff    std::string LoadErrorMessage;
55219820Sjeff
56219820Sjeff    if (CompilationDatabase *DB =
57219820Sjeff           CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
58219820Sjeff      return DB;
59219820Sjeff
60219820Sjeff    if (!HasErrorMessage) {
61219820Sjeff      ErrorStream << "No compilation database found in " << Directory.str()
62219820Sjeff                  << " or any parent directory\n" << LoadErrorMessage;
63219820Sjeff      HasErrorMessage = true;
64219820Sjeff    }
65219820Sjeff
66219820Sjeff    Directory = llvm::sys::path::parent_path(Directory);
67219820Sjeff  }
68219820Sjeff  ErrorMessage = ErrorStream.str();
69219820Sjeff  return NULL;
70219820Sjeff}
71219820Sjeff
72219820SjeffCompilationDatabase *
73219820SjeffCompilationDatabase::autoDetectFromSource(StringRef SourceFile,
74219820Sjeff                                          std::string &ErrorMessage) {
75255932Salfred  SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
76255932Salfred  StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
77255932Salfred
78219820Sjeff  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(Directory,
79242933Sdim                                                                 ErrorMessage);
80242933Sdim
81242933Sdim  if (!DB)
82242933Sdim    ErrorMessage = ("Could not auto-detect compilation database for file \"" +
83242933Sdim                   SourceFile + "\"\n" + ErrorMessage).str();
84242933Sdim  return DB;
85219820Sjeff}
86219820Sjeff
87219820SjeffCompilationDatabase *
88219820SjeffCompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
89219820Sjeff                                             std::string &ErrorMessage) {
90240680Sgavin  SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
91240680Sgavin
92219820Sjeff  CompilationDatabase *DB = findCompilationDatabaseFromDirectory(AbsolutePath,
93219820Sjeff                                                                 ErrorMessage);
94219820Sjeff
95219820Sjeff  if (!DB)
96219820Sjeff    ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
97219820Sjeff                   SourceDir + "\"\n" + ErrorMessage).str();
98219820Sjeff  return DB;
99255932Salfred}
100219820Sjeff
101219820SjeffCompilationDatabasePlugin::~CompilationDatabasePlugin() {}
102219820Sjeff
103219820SjeffFixedCompilationDatabase *
104219820SjeffFixedCompilationDatabase::loadFromCommandLine(int &Argc,
105219820Sjeff                                              const char **Argv,
106255932Salfred                                              Twine Directory) {
107255932Salfred  const char **DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
108219820Sjeff  if (DoubleDash == Argv + Argc)
109219820Sjeff    return NULL;
110255932Salfred  std::vector<std::string> CommandLine(DoubleDash + 1, Argv + Argc);
111219820Sjeff  Argc = DoubleDash - Argv;
112219820Sjeff  return new FixedCompilationDatabase(Directory, CommandLine);
113219820Sjeff}
114219820Sjeff
115219820SjeffFixedCompilationDatabase::
116219820SjeffFixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
117219820Sjeff  std::vector<std::string> ToolCommandLine(1, "clang-tool");
118219820Sjeff  ToolCommandLine.insert(ToolCommandLine.end(),
119219820Sjeff                         CommandLine.begin(), CommandLine.end());
120219820Sjeff  CompileCommands.push_back(CompileCommand(Directory, ToolCommandLine));
121219820Sjeff}
122219820Sjeff
123219820Sjeffstd::vector<CompileCommand>
124219820SjeffFixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
125219820Sjeff  std::vector<CompileCommand> Result(CompileCommands);
126219820Sjeff  Result[0].CommandLine.push_back(FilePath);
127255932Salfred  return Result;
128255932Salfred}
129255932Salfred
130219820Sjeffstd::vector<std::string>
131219820SjeffFixedCompilationDatabase::getAllFiles() const {
132219820Sjeff  return std::vector<std::string>();
133219820Sjeff}
134219820Sjeff
135219820Sjeffstd::vector<CompileCommand>
136219820SjeffFixedCompilationDatabase::getAllCompileCommands() const {
137219820Sjeff  return std::vector<CompileCommand>();
138219820Sjeff}
139219820Sjeff
140219820Sjeff// This anchor is used to force the linker to link in the generated object file
141219820Sjeff// and thus register the JSONCompilationDatabasePlugin.
142219820Sjeffextern volatile int JSONAnchorSource;
143219820Sjeffstatic int JSONAnchorDest = JSONAnchorSource;
144219820Sjeff
145219820Sjeff} // end namespace tooling
146219820Sjeff} // end namespace clang
147219820Sjeff