This commit is contained in:
Fangrui Song 2018-10-15 01:26:13 -07:00
parent 5fbe4eac83
commit 46cfd5504a
6 changed files with 47 additions and 125 deletions

View File

@ -72,20 +72,15 @@ bool TrimPath(Project *project, std::string &path) {
} }
lsCompletionItem BuildCompletionItem(const std::string &path, lsCompletionItem BuildCompletionItem(const std::string &path,
bool use_angle_brackets, bool is_stl) { bool use_angle_brackets) {
lsCompletionItem item; lsCompletionItem item;
item.label = ElideLongPath(path); item.label = ElideLongPath(path);
item.detail = path; // the include path, used in de-duplicating item.detail = path; // the include path, used in de-duplicating
item.textEdit.newText = path; item.textEdit.newText = path;
item.insertTextFormat = lsInsertTextFormat::PlainText; item.insertTextFormat = lsInsertTextFormat::PlainText;
item.use_angle_brackets_ = use_angle_brackets; item.use_angle_brackets_ = use_angle_brackets;
if (is_stl) { item.kind = lsCompletionItemKind::File;
item.kind = lsCompletionItemKind::Module; item.priority_ = 0;
item.priority_ = 2;
} else {
item.kind = lsCompletionItemKind::File;
item.priority_ = 1;
}
return item; return item;
} }
@ -154,8 +149,7 @@ void IncludeComplete::AddFile(const std::string &path) {
std::string trimmed_path = path; std::string trimmed_path = path;
bool use_angle_brackets = TrimPath(project_, trimmed_path); bool use_angle_brackets = TrimPath(project_, trimmed_path);
lsCompletionItem item = lsCompletionItem item = BuildCompletionItem(trimmed_path, use_angle_brackets);
BuildCompletionItem(trimmed_path, use_angle_brackets, false /*is_stl*/);
std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock); std::unique_lock<std::mutex> lock(completion_items_mutex, std::defer_lock);
if (is_scanning) if (is_scanning)
@ -184,7 +178,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
CompletionCandidate candidate; CompletionCandidate candidate;
candidate.absolute_path = directory + path; candidate.absolute_path = directory + path;
candidate.completion_item = candidate.completion_item =
BuildCompletionItem(path, use_angle_brackets, false /*is_stl*/); BuildCompletionItem(path, use_angle_brackets);
results.push_back(candidate); results.push_back(candidate);
}); });

View File

@ -7,7 +7,6 @@
#include "maybe.h" #include "maybe.h"
#include "position.h" #include "position.h"
#include "serializer.h" #include "serializer.h"
#include "symbol.h"
#include "utils.h" #include "utils.h"
#include <clang/Basic/FileManager.h> #include <clang/Basic/FileManager.h>

View File

@ -208,6 +208,14 @@ enum class lsSymbolKind : uint8_t {
}; };
MAKE_REFLECT_TYPE_PROXY(lsSymbolKind); MAKE_REFLECT_TYPE_PROXY(lsSymbolKind);
struct lsSymbolInformation {
std::string_view name;
lsSymbolKind kind;
lsLocation location;
std::optional<std::string_view> containerName;
};
MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName);
struct lsTextDocumentIdentifier { struct lsTextDocumentIdentifier {
lsDocumentUri uri; lsDocumentUri uri;
}; };
@ -382,3 +390,31 @@ MAKE_REFLECT_STRUCT(lsShowMessageParams, type, message);
// encounters a c++ declaration. // encounters a c++ declaration.
enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 }; enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 };
MAKE_REFLECT_TYPE_PROXY(LanguageId); MAKE_REFLECT_TYPE_PROXY(LanguageId);
// The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in
// front of others.
enum class SymbolKind : uint8_t { Invalid, File, Type, Func, Var };
MAKE_REFLECT_TYPE_PROXY(SymbolKind);
enum class Role : uint16_t {
None = 0,
Declaration = 1 << 0,
Definition = 1 << 1,
Reference = 1 << 2,
Read = 1 << 3,
Write = 1 << 4,
Call = 1 << 5,
Dynamic = 1 << 6,
Address = 1 << 7,
Implicit = 1 << 8,
All = (1 << 9) - 1,
};
MAKE_REFLECT_TYPE_PROXY(Role);
inline uint16_t operator&(Role lhs, Role rhs) {
return uint16_t(lhs) & uint16_t(rhs);
}
inline Role operator|(Role lhs, Role rhs) {
return Role(uint16_t(lhs) | uint16_t(rhs));
}

View File

@ -4,7 +4,6 @@
#include "message_handler.h" #include "message_handler.h"
#include "pipeline.hh" #include "pipeline.hh"
#include "query_utils.h" #include "query_utils.h"
#include "symbol.h"
#include <algorithm> #include <algorithm>
using namespace ccls; using namespace ccls;

View File

@ -27,78 +27,15 @@
#include <malloc.h> #include <malloc.h>
#endif #endif
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/Path.h>
#include <string> #include <string>
namespace {
// Returns the canonicalized absolute pathname, without expanding symbolic
// links. This is a variant of realpath(2), C++ rewrite of
// https://github.com/freebsd/freebsd/blob/master/lib/libc/stdlib/realpath.c
std::optional<std::string> RealPathNotExpandSymlink(std::string path) {
if (path.empty()) {
errno = EINVAL;
return std::nullopt;
}
if (path[0] == '\0') {
errno = ENOENT;
return std::nullopt;
}
// Do not use PATH_MAX because it is tricky on Linux.
// See https://eklitzke.org/path-max-is-tricky
char tmp[1024];
std::string resolved;
size_t i = 0;
struct stat sb;
if (path[0] == '/') {
resolved = "/";
i = 1;
} else {
if (!getcwd(tmp, sizeof tmp))
return std::nullopt;
resolved = tmp;
}
while (i < path.size()) {
auto j = path.find('/', i);
if (j == std::string::npos)
j = path.size();
auto next_token = path.substr(i, j - i);
i = j + 1;
if (resolved.back() != '/')
resolved += '/';
if (next_token.empty() || next_token == ".") {
// Handle consequential slashes and "."
continue;
} else if (next_token == "..") {
// Strip the last path component except when it is single "/"
if (resolved.size() > 1)
resolved.resize(resolved.rfind('/', resolved.size() - 2) + 1);
continue;
}
// Append the next path component.
// Here we differ from realpath(3), we use stat(2) instead of
// lstat(2) because we do not want to resolve symlinks.
resolved += next_token;
if (stat(resolved.c_str(), &sb) != 0)
return std::nullopt;
if (!S_ISDIR(sb.st_mode) && j < path.size()) {
errno = ENOTDIR;
return std::nullopt;
}
}
// Remove trailing slash except when a single "/".
if (resolved.size() > 1 && resolved.back() == '/')
resolved.pop_back();
return resolved;
}
} // namespace
std::string NormalizePath(const std::string &path) { std::string NormalizePath(const std::string &path) {
std::optional<std::string> resolved = RealPathNotExpandSymlink(path); llvm::SmallString<256> P(path);
return resolved ? *resolved : path; llvm::sys::path::remove_dots(P, true);
return {P.data(), P.size()};
} }
void FreeUnusedMemory() { void FreeUnusedMemory() {

View File

@ -1,43 +0,0 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "lsp.h"
#include "serializer.h"
// The order matters. In FindSymbolsAtLocation, we want Var/Func ordered in
// front of others.
enum class SymbolKind : uint8_t { Invalid, File, Type, Func, Var };
MAKE_REFLECT_TYPE_PROXY(SymbolKind);
enum class Role : uint16_t {
None = 0,
Declaration = 1 << 0,
Definition = 1 << 1,
Reference = 1 << 2,
Read = 1 << 3,
Write = 1 << 4,
Call = 1 << 5,
Dynamic = 1 << 6,
Address = 1 << 7,
Implicit = 1 << 8,
All = (1 << 9) - 1,
};
MAKE_REFLECT_TYPE_PROXY(Role);
inline uint16_t operator&(Role lhs, Role rhs) {
return uint16_t(lhs) & uint16_t(rhs);
}
inline Role operator|(Role lhs, Role rhs) {
return Role(uint16_t(lhs) | uint16_t(rhs));
}
struct lsSymbolInformation {
std::string_view name;
lsSymbolKind kind;
lsLocation location;
std::optional<std::string_view> containerName;
};
MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName);