mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-27 10:02:03 +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
78e323b662
commit
8fea558f95
@ -188,7 +188,6 @@ target_sources(ccls PRIVATE
|
|||||||
src/include_complete.cc
|
src/include_complete.cc
|
||||||
src/indexer.cc
|
src/indexer.cc
|
||||||
src/method.cc
|
src/method.cc
|
||||||
src/language.cc
|
|
||||||
src/log.cc
|
src/log.cc
|
||||||
src/lsp.cc
|
src/lsp.cc
|
||||||
src/match.cc
|
src/match.cc
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "language.h"
|
|
||||||
#include "lsp.h"
|
#include "lsp.h"
|
||||||
#include "lsp_diagnostic.h"
|
#include "lsp_diagnostic.h"
|
||||||
#include "maybe.h"
|
#include "maybe.h"
|
||||||
@ -23,6 +22,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using Usr = uint64_t;
|
using Usr = uint64_t;
|
||||||
|
enum class LanguageId;
|
||||||
|
|
||||||
struct SymbolIdx {
|
struct SymbolIdx {
|
||||||
Usr usr;
|
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;
|
std::vector<lsLocation> result;
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, 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;
|
std::string g_init_options;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
opt<bool> opt_help("h", desc("Alias for -help"));
|
OptionCategory C("ccls options");
|
||||||
opt<int> opt_verbose("v", desc("verbosity"), init(0));
|
|
||||||
|
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("!"),
|
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_init("init", desc("extra initialization options in JSON"),
|
||||||
opt<std::string> opt_log_file("log-file", desc("log"), value_desc("filename"));
|
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"),
|
opt<std::string> opt_log_file_append("log-file-append", desc("log"),
|
||||||
value_desc("filename"));
|
value_desc("filename"), cat(C));
|
||||||
|
|
||||||
list<std::string> opt_extra(Positional, ZeroOrMore, desc("extra"));
|
|
||||||
|
|
||||||
void CloseLog() { fclose(ccls::log::file); }
|
void CloseLog() { fclose(ccls::log::file); }
|
||||||
|
|
||||||
@ -50,6 +52,10 @@ int main(int argc, char **argv) {
|
|||||||
TraceMe();
|
TraceMe();
|
||||||
sys::PrintStackTraceOnErrorSignal(argv[0]);
|
sys::PrintStackTraceOnErrorSignal(argv[0]);
|
||||||
|
|
||||||
|
for (auto &I : TopLevelSubCommand->OptionsMap)
|
||||||
|
if (I.second->Category != &C)
|
||||||
|
I.second->setHiddenFlag(ReallyHidden);
|
||||||
|
|
||||||
ParseCommandLineOptions(argc, argv,
|
ParseCommandLineOptions(argc, argv,
|
||||||
"C/C++/Objective-C language server\n\n"
|
"C/C++/Objective-C language server\n\n"
|
||||||
"See more on https://github.com/MaskRay/ccls/wiki");
|
"See more on https://github.com/MaskRay/ccls/wiki");
|
||||||
|
@ -127,7 +127,8 @@ struct Handler_TextDocumentDidOpen
|
|||||||
|
|
||||||
// Submit new index request if it is not a header file or there is no
|
// Submit new index request if it is not a header file or there is no
|
||||||
// pending index request.
|
// 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::pending_index_requests)
|
||||||
pipeline::Index(path, args, IndexMode::Normal);
|
pipeline::Index(path, args, IndexMode::Normal);
|
||||||
|
|
||||||
|
@ -9,6 +9,18 @@ using namespace ccls;
|
|||||||
namespace {
|
namespace {
|
||||||
MethodType kMethodType = "textDocument/hover";
|
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.
|
// Returns the hover or detailed name for `sym`, if any.
|
||||||
std::pair<std::optional<lsMarkedString>, std::optional<lsMarkedString>>
|
std::pair<std::optional<lsMarkedString>, std::optional<lsMarkedString>>
|
||||||
GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
|
||||||
#include "filesystem.hh"
|
#include "filesystem.hh"
|
||||||
#include "language.h"
|
|
||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "pipeline.hh"
|
#include "pipeline.hh"
|
||||||
@ -15,6 +14,7 @@
|
|||||||
|
|
||||||
#include <clang/Driver/Compilation.h>
|
#include <clang/Driver/Compilation.h>
|
||||||
#include <clang/Driver/Driver.h>
|
#include <clang/Driver/Driver.h>
|
||||||
|
#include <clang/Driver/Types.h>
|
||||||
#include <clang/Frontend/CompilerInstance.h>
|
#include <clang/Frontend/CompilerInstance.h>
|
||||||
#include <clang/Tooling/CompilationDatabase.h>
|
#include <clang/Tooling/CompilationDatabase.h>
|
||||||
#include <llvm/ADT/STLExtras.h>
|
#include <llvm/ADT/STLExtras.h>
|
||||||
@ -35,6 +35,25 @@ using namespace ccls;
|
|||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace llvm;
|
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 {
|
namespace {
|
||||||
|
|
||||||
enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand };
|
enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand };
|
||||||
@ -64,7 +83,7 @@ struct ProjectProcessor {
|
|||||||
// Expand %c %cpp %clang
|
// Expand %c %cpp %clang
|
||||||
std::vector<const char *> args;
|
std::vector<const char *> args;
|
||||||
args.reserve(entry.args.size() + g_config->clang.extraArgs.size() + 1);
|
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) {
|
for (const char *arg : entry.args) {
|
||||||
if (strncmp(arg, "%c ", 3) == 0) {
|
if (strncmp(arg, "%c ", 3) == 0) {
|
||||||
if (lang == LanguageId::C)
|
if (lang == LanguageId::C)
|
||||||
@ -86,7 +105,7 @@ struct ProjectProcessor {
|
|||||||
size_t hash = std::hash<std::string>{}(entry.directory);
|
size_t hash = std::hash<std::string>{}(entry.directory);
|
||||||
for (auto &arg : args) {
|
for (auto &arg : args) {
|
||||||
if (arg[0] != '-' && EndsWith(arg, base_name)) {
|
if (arg[0] != '-' && EndsWith(arg, base_name)) {
|
||||||
const LanguageId lang = SourceFileLanguage(arg);
|
LanguageId lang = lookupExtension(arg).first;
|
||||||
if (lang != LanguageId::Unknown) {
|
if (lang != LanguageId::Unknown) {
|
||||||
hash_combine(hash, size_t(lang));
|
hash_combine(hash, size_t(lang));
|
||||||
continue;
|
continue;
|
||||||
@ -170,12 +189,6 @@ ReadCompilerArgumentsFromFile(const std::string &path) {
|
|||||||
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig *config) {
|
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig *config) {
|
||||||
std::vector<Project::Entry> result;
|
std::vector<Project::Entry> result;
|
||||||
config->mode = ProjectMode::DotCcls;
|
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::unordered_map<std::string, std::vector<const char *>> folder_args;
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
@ -184,7 +197,8 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig *config) {
|
|||||||
GetFilesInFolder(root, true /*recursive*/,
|
GetFilesInFolder(root, true /*recursive*/,
|
||||||
true /*add_folder_to_path*/,
|
true /*add_folder_to_path*/,
|
||||||
[&folder_args, &files](const std::string &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);
|
files.push_back(path);
|
||||||
} else if (sys::path::filename(path) == ".ccls") {
|
} else if (sys::path::filename(path) == ".ccls") {
|
||||||
std::vector<const char *> args = ReadCompilerArgumentsFromFile(path);
|
std::vector<const char *> args = ReadCompilerArgumentsFromFile(path);
|
||||||
@ -235,14 +249,13 @@ std::vector<Project::Entry>
|
|||||||
LoadEntriesFromDirectory(ProjectConfig *project,
|
LoadEntriesFromDirectory(ProjectConfig *project,
|
||||||
const std::string &opt_compdb_dir) {
|
const std::string &opt_compdb_dir) {
|
||||||
// If there is a .ccls file always load using directory listing.
|
// If there is a .ccls file always load using directory listing.
|
||||||
SmallString<256> Path;
|
SmallString<256> Path, CclsPath;
|
||||||
sys::path::append(Path, project->root, ".ccls");
|
sys::path::append(CclsPath, project->root, ".ccls");
|
||||||
if (sys::fs::exists(Path))
|
if (sys::fs::exists(CclsPath))
|
||||||
return LoadFromDirectoryListing(project);
|
return LoadFromDirectoryListing(project);
|
||||||
|
|
||||||
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
||||||
std::string comp_db_dir;
|
std::string comp_db_dir;
|
||||||
Path.clear();
|
|
||||||
if (g_config->compilationDatabaseCommand.empty()) {
|
if (g_config->compilationDatabaseCommand.empty()) {
|
||||||
project->mode = ProjectMode::CompileCommandsJson;
|
project->mode = ProjectMode::CompileCommandsJson;
|
||||||
// Try to load compile_commands.json, but fallback to a project listing.
|
// Try to load compile_commands.json, but fallback to a project listing.
|
||||||
@ -284,8 +297,8 @@ LoadEntriesFromDirectory(ProjectConfig *project,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (!CDB) {
|
if (!CDB) {
|
||||||
LOG_S(WARNING) << "failed to load " << Path.c_str() << " " << err_msg;
|
LOG_S(WARNING) << "no .ccls or compile_commands.json . Consider adding one";
|
||||||
return {};
|
return LoadFromDirectoryListing(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_S(INFO) << "loaded " << Path.c_str();
|
LOG_S(INFO) << "loaded " << Path.c_str();
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "lsp.h"
|
||||||
#include "method.h"
|
#include "method.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -14,6 +15,8 @@
|
|||||||
|
|
||||||
struct WorkingFiles;
|
struct WorkingFiles;
|
||||||
|
|
||||||
|
std::pair<LanguageId, bool> lookupExtension(std::string_view filename);
|
||||||
|
|
||||||
struct Project {
|
struct Project {
|
||||||
struct Entry {
|
struct Entry {
|
||||||
std::string root;
|
std::string root;
|
||||||
|
Loading…
Reference in New Issue
Block a user