Ejemplo n.º 1
0
std::vector<CompileCommand>
JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
  llvm::SmallString<128> NativeFilePath;
  llvm::sys::path::native(FilePath, NativeFilePath);
  std::vector<StringRef> PossibleMatches;
  std::string Error;
  llvm::raw_string_ostream ES(Error);
  StringRef Match = MatchTrie.findEquivalent(NativeFilePath.str(), ES);
  if (Match.empty()) {
    if (Error.empty())
      Error = "No match found.";
    llvm::outs() << Error << "\n";
    return std::vector<CompileCommand>();
  }
  llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
    CommandsRefI = IndexByFile.find(Match);
  if (CommandsRefI == IndexByFile.end())
    return std::vector<CompileCommand>();
  const std::vector<CompileCommandRef> &CommandsRef = CommandsRefI->getValue();
  std::vector<CompileCommand> Commands;
  for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
    llvm::SmallString<8> DirectoryStorage;
    llvm::SmallString<1024> CommandStorage;
    Commands.push_back(CompileCommand(
      // FIXME: Escape correctly:
      CommandsRef[I].first->getValue(DirectoryStorage),
      unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage))));
  }
  return Commands;
}
Ejemplo n.º 2
0
    std::vector<std::string> nextCommand() {
        std::string line;

        if (std::getline(std::cin, line)) {
            return unescapeCommandLine(line);
        }

        return std::vector<std::string>(1, "exit");
    }
std::vector<CompileCommand>
JSONCompilationDatabase::getCompileCommands(StringRef FilePath) const {
  llvm::SmallString<128> NativeFilePath;
  llvm::sys::path::native(FilePath, NativeFilePath);
  llvm::StringMap< std::vector<CompileCommandRef> >::const_iterator
    CommandsRefI = IndexByFile.find(NativeFilePath);
  if (CommandsRefI == IndexByFile.end())
    return std::vector<CompileCommand>();
  const std::vector<CompileCommandRef> &CommandsRef = CommandsRefI->getValue();
  std::vector<CompileCommand> Commands;
  for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
    llvm::SmallString<8> DirectoryStorage;
    llvm::SmallString<1024> CommandStorage;
    Commands.push_back(CompileCommand(
      // FIXME: Escape correctly:
      CommandsRef[I].first->getValue(DirectoryStorage),
      unescapeCommandLine(CommandsRef[I].second->getValue(CommandStorage))));
  }
  return Commands;
}
Ejemplo n.º 4
0
Command *CommandParser::parse(const std::vector<std::string> &argv) {
    command_.clear();

    if (argv.begin() == argv.end()) {
        std::clog << "error: no command specified.\n"
                  "See 'irony-server help' to list available commands\n";
        return 0;
    }

    const std::string &actionStr = argv[0];

    command_.action = actionFromString(actionStr);

    bool handleUnsaved = false;
    bool readCompileOptions = false;
    std::vector<std::function<bool(const std::string &)>> positionalArgs;

    switch (command_.action) {
    case Command::SetDebug:
        positionalArgs.push_back(OptionConverter(&command_.opt));
        break;

    case Command::Parse:
        positionalArgs.push_back(StringConverter(&command_.file));
        handleUnsaved = true;
        readCompileOptions = true;
        break;

    case Command::Complete:
        positionalArgs.push_back(StringConverter(&command_.file));
        positionalArgs.push_back(UnsignedIntConverter(&command_.line));
        positionalArgs.push_back(UnsignedIntConverter(&command_.column));
        handleUnsaved = true;
        readCompileOptions = true;
        break;

    case Command::GetType:
        positionalArgs.push_back(UnsignedIntConverter(&command_.line));
        positionalArgs.push_back(UnsignedIntConverter(&command_.column));
        break;

    case Command::Diagnostics:
    case Command::Help:
    case Command::Exit:
        // no-arguments commands
        break;

    case Command::GetCompileOptions:
        positionalArgs.push_back(StringConverter(&command_.dir));
        positionalArgs.push_back(StringConverter(&command_.file));
        break;

    case Command::Unknown:
        std::clog << "error: invalid command specified: " << actionStr << "\n";
        return 0;
    }

    auto argIt = argv.begin() + 1;
    int argCount = std::distance(argIt, argv.end());

    // parse optional arguments come first
    while (argIt != argv.end()) {
        // '-' is allowed as a "default" file, this isn't an option but a positional
        // argument
        if ((*argIt)[0] != '-' || *argIt == "-")
            break;

        const std::string &opt = *argIt;

        ++argIt;
        argCount--;

        if (handleUnsaved) {
            // TODO: handle multiple unsaved files
            if (opt == "--num-unsaved=1") {
                command_.unsavedFiles.resize(1);
            }
        } else {
            std::clog << "error: invalid option for '" << actionStr << "': '" << opt
                      << "' unknown\n";
            return 0;
        }
    }

    if (argCount != static_cast<int>(positionalArgs.size())) {
        std::clog << "error: invalid number of arguments for '" << actionStr
                  << "' (requires " << positionalArgs.size() << " got " << argCount
                  << ")\n";
        return 0;
    }

    for (auto fn : positionalArgs) {
        if (!fn(*argIt)) {
            std::clog << "error: parsing command '" << actionStr
                      << "': invalid argument '" << *argIt << "'\n";
            return 0;
        }
        ++argIt;
    }

    // '-' is used as a special file to inform that the buffer hasn't been saved
    // on disk and only the buffer content is available. libclang needs a file, so
    // this is treated as a special value for irony-server to create a temporary
    // file for this. note taht libclang will gladly accept '-' as a filename but
    // we don't want to let this happen since irony already reads stdin.
    if (command_.file == "-") {
        command_.file = tempFile_.getPath();
    }

    // When a file is provided, the next line contains the compilation options to
    // pass to libclang.
    if (readCompileOptions) {
        std::string compileOptions;
        std::getline(std::cin, compileOptions);

        command_.flags = unescapeCommandLine(compileOptions);
    }

    // read unsaved files
    // filename
    // filesize
    // <file content...>
    for (auto &p : command_.unsavedFiles) {
        std::getline(std::cin, p.first);

        unsigned length;
        std::string filesizeStr;
        std::getline(std::cin, filesizeStr);

        UnsignedIntConverter uintConverter(&length);

        if (!uintConverter(filesizeStr)) {
            std::clog << "error: invalid file size '" << filesizeStr << "'\n";
            return 0;
        }

        p.second.resize(length);
        std::cin.read(p.second.data(), p.second.size());

        CXUnsavedFile cxUnsavedFile;

        cxUnsavedFile.Filename = p.first.c_str();
        cxUnsavedFile.Contents = p.second.data();
        cxUnsavedFile.Length = p.second.size();
        command_.cxUnsavedFiles.push_back(cxUnsavedFile);

        char nl;
        std::cin.read(&nl, 1);
        if (nl != '\n') {
            std::clog << "error: missing newline for unsaved file content\n";
            return 0;
        }
    }

    return &command_;
}