mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-24 16:45:07 +00:00
Misc changes to project
* Better LanguageId detection with clangDriver (e.g. .cu -> types::TY_CUDA) * fallback when there is no .ccls or compile_commands.json Also Hide clangTooling options from --help
This commit is contained in:
parent
40b47f9ca3
commit
4a1eea75db
@ -188,7 +188,6 @@ target_sources(ccls PRIVATE
|
||||
src/include_complete.cc
|
||||
src/indexer.cc
|
||||
src/method.cc
|
||||
src/language.cc
|
||||
src/log.cc
|
||||
src/lsp.cc
|
||||
src/match.cc
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "language.h"
|
||||
#include "lsp.h"
|
||||
#include "lsp_diagnostic.h"
|
||||
#include "maybe.h"
|
||||
@ -23,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
using Usr = uint64_t;
|
||||
enum class LanguageId;
|
||||
|
||||
struct SymbolIdx {
|
||||
Usr usr;
|
||||
|
@ -1,33 +0,0 @@
|
||||
// Copyright 2017-2018 ccls Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "language.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
LanguageId SourceFileLanguage(std::string_view path) {
|
||||
if (EndsWith(path, ".c"))
|
||||
return LanguageId::C;
|
||||
else if (EndsWith(path, ".cpp") || EndsWith(path, ".cc"))
|
||||
return LanguageId::Cpp;
|
||||
else if (EndsWith(path, ".mm"))
|
||||
return LanguageId::ObjCpp;
|
||||
else if (EndsWith(path, ".m"))
|
||||
return LanguageId::ObjC;
|
||||
return LanguageId::Unknown;
|
||||
}
|
||||
|
||||
const char *LanguageIdentifier(LanguageId lang) {
|
||||
switch (lang) {
|
||||
case LanguageId::C:
|
||||
return "c";
|
||||
case LanguageId::Cpp:
|
||||
return "cpp";
|
||||
case LanguageId::ObjC:
|
||||
return "objective-c";
|
||||
case LanguageId::ObjCpp:
|
||||
return "objective-cpp";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2017-2018 ccls Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "serializer.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
// Used to identify the language at a file level. The ordering is important, as
|
||||
// a file previously identified as `C`, will be changed to `Cpp` if it
|
||||
// encounters a c++ declaration.
|
||||
enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 };
|
||||
MAKE_REFLECT_TYPE_PROXY(LanguageId);
|
||||
|
||||
LanguageId SourceFileLanguage(std::string_view path);
|
||||
const char *LanguageIdentifier(LanguageId lang);
|
@ -334,3 +334,9 @@ struct Out_LocationList : public lsOutMessage<Out_LocationList> {
|
||||
std::vector<lsLocation> result;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result);
|
||||
|
||||
// Used to identify the language at a file level. The ordering is important, as
|
||||
// a file previously identified as `C`, will be changed to `Cpp` if it
|
||||
// encounters a c++ declaration.
|
||||
enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 };
|
||||
MAKE_REFLECT_TYPE_PROXY(LanguageId);
|
||||
|
22
src/main.cc
22
src/main.cc
@ -30,17 +30,19 @@ using namespace llvm::cl;
|
||||
std::string g_init_options;
|
||||
|
||||
namespace {
|
||||
opt<bool> opt_help("h", desc("Alias for -help"));
|
||||
opt<int> opt_verbose("v", desc("verbosity"), init(0));
|
||||
OptionCategory C("ccls options");
|
||||
|
||||
opt<bool> opt_help("h", desc("Alias for -help"), cat(C));
|
||||
opt<int> opt_verbose("v", desc("verbosity"), init(0), cat(C));
|
||||
opt<std::string> opt_test_index("test-index", ValueOptional, init("!"),
|
||||
desc("run index tests"));
|
||||
desc("run index tests"), cat(C));
|
||||
|
||||
opt<std::string> opt_init("init", desc("extra initialization options"));
|
||||
opt<std::string> opt_log_file("log-file", desc("log"), value_desc("filename"));
|
||||
opt<std::string> opt_init("init", desc("extra initialization options in JSON"),
|
||||
cat(C));
|
||||
opt<std::string> opt_log_file("log-file", desc("log"), value_desc("filename"),
|
||||
cat(C));
|
||||
opt<std::string> opt_log_file_append("log-file-append", desc("log"),
|
||||
value_desc("filename"));
|
||||
|
||||
list<std::string> opt_extra(Positional, ZeroOrMore, desc("extra"));
|
||||
value_desc("filename"), cat(C));
|
||||
|
||||
void CloseLog() { fclose(ccls::log::file); }
|
||||
|
||||
@ -50,6 +52,10 @@ int main(int argc, char **argv) {
|
||||
TraceMe();
|
||||
sys::PrintStackTraceOnErrorSignal(argv[0]);
|
||||
|
||||
for (auto &I : TopLevelSubCommand->OptionsMap)
|
||||
if (I.second->Category != &C)
|
||||
I.second->setHiddenFlag(ReallyHidden);
|
||||
|
||||
ParseCommandLineOptions(argc, argv,
|
||||
"C/C++/Objective-C language server\n\n"
|
||||
"See more on https://github.com/MaskRay/ccls/wiki");
|
||||
|
@ -115,7 +115,8 @@ struct Handler_TextDocumentDidOpen
|
||||
|
||||
// Submit new index request if it is not a header file or there is no
|
||||
// pending index request.
|
||||
if (SourceFileLanguage(path) != LanguageId::Unknown ||
|
||||
std::pair<LanguageId, bool> lang = lookupExtension(path);
|
||||
if ((lang.first != LanguageId::Unknown && !lang.second) ||
|
||||
!pipeline::pending_index_requests)
|
||||
pipeline::Index(path, args, IndexMode::Normal);
|
||||
|
||||
|
@ -9,6 +9,18 @@ using namespace ccls;
|
||||
namespace {
|
||||
MethodType kMethodType = "textDocument/hover";
|
||||
|
||||
const char *LanguageIdentifier(LanguageId lang) {
|
||||
switch (lang) {
|
||||
// clang-format off
|
||||
case LanguageId::C: return "c";
|
||||
case LanguageId::Cpp: return "cpp";
|
||||
case LanguageId::ObjC: return "objective-c";
|
||||
case LanguageId::ObjCpp: return "objective-cpp";
|
||||
default: return "";
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the hover or detailed name for `sym`, if any.
|
||||
std::pair<std::optional<lsMarkedString>, std::optional<lsMarkedString>>
|
||||
GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "project.h"
|
||||
|
||||
#include "filesystem.hh"
|
||||
#include "language.h"
|
||||
#include "log.hh"
|
||||
#include "match.h"
|
||||
#include "pipeline.hh"
|
||||
@ -15,6 +14,7 @@
|
||||
|
||||
#include <clang/Driver/Compilation.h>
|
||||
#include <clang/Driver/Driver.h>
|
||||
#include <clang/Driver/Types.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Tooling/CompilationDatabase.h>
|
||||
#include <llvm/ADT/STLExtras.h>
|
||||
@ -35,6 +35,25 @@ using namespace ccls;
|
||||
using namespace clang;
|
||||
using namespace llvm;
|
||||
|
||||
std::pair<LanguageId, bool> lookupExtension(std::string_view filename) {
|
||||
using namespace clang::driver;
|
||||
auto I = types::lookupTypeForExtension(
|
||||
sys::path::extension({filename.data(), filename.size()}).substr(1));
|
||||
bool header = I == types::TY_CHeader || I == types::TY_CXXHeader ||
|
||||
I == types::TY_ObjCXXHeader;
|
||||
bool objc = types::isObjC(I);
|
||||
LanguageId ret;
|
||||
if (types::isCXX(I))
|
||||
ret = objc ? LanguageId::ObjCpp : LanguageId::Cpp;
|
||||
else if (objc)
|
||||
ret = LanguageId::ObjC;
|
||||
else if (I == types::TY_C || I == types::TY_CHeader)
|
||||
ret = LanguageId::C;
|
||||
else
|
||||
ret = LanguageId::Unknown;
|
||||
return {ret, header};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand };
|
||||
@ -64,7 +83,7 @@ struct ProjectProcessor {
|
||||
// Expand %c %cpp %clang
|
||||
std::vector<const char *> args;
|
||||
args.reserve(entry.args.size() + g_config->clang.extraArgs.size() + 1);
|
||||
const LanguageId lang = SourceFileLanguage(entry.filename);
|
||||
const LanguageId lang = lookupExtension(entry.filename).first;
|
||||
for (const char *arg : entry.args) {
|
||||
if (strncmp(arg, "%c ", 3) == 0) {
|
||||
if (lang == LanguageId::C)
|
||||
@ -86,7 +105,7 @@ struct ProjectProcessor {
|
||||
size_t hash = std::hash<std::string>{}(entry.directory);
|
||||
for (auto &arg : args) {
|
||||
if (arg[0] != '-' && EndsWith(arg, base_name)) {
|
||||
const LanguageId lang = SourceFileLanguage(arg);
|
||||
LanguageId lang = lookupExtension(arg).first;
|
||||
if (lang != LanguageId::Unknown) {
|
||||
hash_combine(hash, size_t(lang));
|
||||
continue;
|
||||
@ -170,12 +189,6 @@ ReadCompilerArgumentsFromFile(const std::string &path) {
|
||||
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig *config) {
|
||||
std::vector<Project::Entry> result;
|
||||
config->mode = ProjectMode::DotCcls;
|
||||
SmallString<256> Path;
|
||||
sys::path::append(Path, config->root, ".ccls");
|
||||
LOG_IF_S(WARNING, !sys::fs::exists(Path) && g_config->clang.extraArgs.empty())
|
||||
<< "ccls has no clang arguments. Use either "
|
||||
"compile_commands.json or .ccls, See ccls README for "
|
||||
"more information.";
|
||||
|
||||
std::unordered_map<std::string, std::vector<const char *>> folder_args;
|
||||
std::vector<std::string> files;
|
||||
@ -184,7 +197,8 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig *config) {
|
||||
GetFilesInFolder(root, true /*recursive*/,
|
||||
true /*add_folder_to_path*/,
|
||||
[&folder_args, &files](const std::string &path) {
|
||||
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
||||
std::pair<LanguageId, bool> lang = lookupExtension(path);
|
||||
if (lang.first != LanguageId::Unknown && !lang.second) {
|
||||
files.push_back(path);
|
||||
} else if (sys::path::filename(path) == ".ccls") {
|
||||
std::vector<const char *> args = ReadCompilerArgumentsFromFile(path);
|
||||
@ -235,14 +249,13 @@ std::vector<Project::Entry>
|
||||
LoadEntriesFromDirectory(ProjectConfig *project,
|
||||
const std::string &opt_compdb_dir) {
|
||||
// If there is a .ccls file always load using directory listing.
|
||||
SmallString<256> Path;
|
||||
sys::path::append(Path, project->root, ".ccls");
|
||||
if (sys::fs::exists(Path))
|
||||
SmallString<256> Path, CclsPath;
|
||||
sys::path::append(CclsPath, project->root, ".ccls");
|
||||
if (sys::fs::exists(CclsPath))
|
||||
return LoadFromDirectoryListing(project);
|
||||
|
||||
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
||||
std::string comp_db_dir;
|
||||
Path.clear();
|
||||
if (g_config->compilationDatabaseCommand.empty()) {
|
||||
project->mode = ProjectMode::CompileCommandsJson;
|
||||
// Try to load compile_commands.json, but fallback to a project listing.
|
||||
@ -284,8 +297,8 @@ LoadEntriesFromDirectory(ProjectConfig *project,
|
||||
#endif
|
||||
}
|
||||
if (!CDB) {
|
||||
LOG_S(WARNING) << "failed to load " << Path.c_str() << " " << err_msg;
|
||||
return {};
|
||||
LOG_S(WARNING) << "no .ccls or compile_commands.json . Consider adding one";
|
||||
return LoadFromDirectoryListing(project);
|
||||
}
|
||||
|
||||
LOG_S(INFO) << "loaded " << Path.c_str();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include "lsp.h"
|
||||
#include "method.h"
|
||||
|
||||
#include <functional>
|
||||
@ -14,6 +15,8 @@
|
||||
|
||||
struct WorkingFiles;
|
||||
|
||||
std::pair<LanguageId, bool> lookupExtension(std::string_view filename);
|
||||
|
||||
struct Project {
|
||||
struct Entry {
|
||||
std::string root;
|
||||
|
Loading…
Reference in New Issue
Block a user