ccls/src/indexer.h

308 lines
8.9 KiB
C
Raw Normal View History

2018-08-21 05:27:52 +00:00
/* Copyright 2017-2018 ccls Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
2017-02-22 08:52:00 +00:00
#pragma once
2018-02-20 03:06:48 +00:00
#include "language.h"
#include "lsp.h"
2018-07-15 07:45:51 +00:00
#include "lsp_diagnostic.h"
#include "maybe.h"
2017-09-22 01:14:57 +00:00
#include "position.h"
#include "serializer.h"
#include "symbol.h"
2017-09-22 01:14:57 +00:00
#include "utils.h"
2018-09-23 20:31:06 +00:00
#include <clang/Basic/FileManager.h>
#include <clang/Basic/Specifiers.h>
#include <llvm/ADT/CachedHashString.h>
#include <llvm/ADT/DenseMap.h>
2018-08-09 17:08:14 +00:00
#include <stdint.h>
2018-03-31 05:05:21 +00:00
#include <string_view>
2018-05-04 04:20:10 +00:00
#include <unordered_map>
2017-04-14 22:30:33 +00:00
#include <vector>
2017-03-25 20:32:44 +00:00
2018-07-07 22:25:25 +00:00
using Usr = uint64_t;
struct SymbolIdx {
Usr usr;
SymbolKind kind;
2018-08-09 17:08:14 +00:00
bool operator==(const SymbolIdx &o) const {
return usr == o.usr && kind == o.kind;
}
2018-08-09 17:08:14 +00:00
bool operator<(const SymbolIdx &o) const {
return usr != o.usr ? usr < o.usr : kind < o.kind;
}
};
MAKE_REFLECT_STRUCT(SymbolIdx, usr, kind);
struct Reference {
Range range;
Usr usr;
2018-02-09 17:42:10 +00:00
SymbolKind kind;
Role role;
bool Valid() const { return range.Valid(); }
operator SymbolIdx() const { return {usr, kind}; }
std::tuple<Range, Usr, SymbolKind, Role> ToTuple() const {
return std::make_tuple(range, usr, kind, role);
}
2018-08-09 17:08:14 +00:00
bool operator==(const Reference &o) const { return ToTuple() == o.ToTuple(); }
bool operator<(const Reference &o) const { return ToTuple() < o.ToTuple(); }
};
// |id,kind| refer to the referenced entity.
2018-06-01 04:21:34 +00:00
struct SymbolRef : Reference {};
MAKE_HASHABLE(SymbolRef, t.range, t.usr, t.kind, t.role);
// Represents an occurrence of a variable/type, |usr,kind| refer to the lexical
// parent.
struct Use : Reference {
// |file| is used in Query* but not in Index*
int file_id = -1;
2018-08-09 17:08:14 +00:00
bool operator==(const Use &o) const {
// lexical container info is ignored.
return range == o.range && file_id == o.file_id;
}
2017-02-22 08:52:00 +00:00
};
MAKE_HASHABLE(Use, t.range, t.file_id)
2017-02-22 08:52:00 +00:00
struct DeclRef : Use {
Range extent;
};
MAKE_HASHABLE(DeclRef, t.range, t.file_id)
2018-08-09 17:08:14 +00:00
void Reflect(Reader &visitor, Reference &value);
void Reflect(Writer &visitor, Reference &value);
void Reflect(Reader &visitor, Use &value);
void Reflect(Writer &visitor, Use &value);
void Reflect(Reader &visitor, DeclRef &value);
void Reflect(Writer &visitor, DeclRef &value);
2017-02-22 08:52:00 +00:00
2018-08-09 17:08:14 +00:00
template <typename D> struct NameMixin {
std::string_view Name(bool qualified) const {
2018-08-09 17:08:14 +00:00
auto self = static_cast<const D *>(this);
return qualified
? std::string_view(self->detailed_name + self->qual_name_offset,
self->short_name_offset -
self->qual_name_offset +
self->short_name_size)
: std::string_view(self->detailed_name + self->short_name_offset,
self->short_name_size);
}
};
struct FuncDef : NameMixin<FuncDef> {
2017-02-22 08:52:00 +00:00
// General metadata.
2018-08-09 17:08:14 +00:00
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
Maybe<Use> spell;
Maybe<Use> extent;
2017-04-05 08:06:18 +00:00
// Method this method overrides.
std::vector<Usr> bases;
2017-02-22 08:52:00 +00:00
// Local variables or parameters.
std::vector<Usr> vars;
2017-02-22 08:52:00 +00:00
// Functions that this function calls.
std::vector<SymbolRef> callees;
int file_id = -1;
int16_t qual_name_offset = 0;
int16_t short_name_offset = 0;
int16_t short_name_size = 0;
lsSymbolKind kind = lsSymbolKind::Unknown;
uint8_t storage = clang::SC_None;
std::vector<Usr> GetBases() const { return bases; }
2017-02-25 06:08:14 +00:00
};
2018-08-09 17:08:14 +00:00
MAKE_REFLECT_STRUCT(FuncDef, detailed_name, qual_name_offset, short_name_offset,
short_name_size, kind, storage, hover, comments, spell,
extent, bases, vars, callees);
2017-02-25 06:08:14 +00:00
struct IndexFunc : NameMixin<IndexFunc> {
using Def = FuncDef;
2018-01-13 08:10:39 +00:00
Usr usr;
Def def;
std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived;
2017-02-22 08:52:00 +00:00
};
2017-02-25 23:59:09 +00:00
struct TypeDef : NameMixin<TypeDef> {
2018-08-09 17:08:14 +00:00
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
2018-02-11 04:30:27 +00:00
Maybe<Use> spell;
Maybe<Use> extent;
2017-02-22 08:52:00 +00:00
std::vector<Usr> bases;
2017-02-22 08:52:00 +00:00
// Types, functions, and variables defined in this type.
std::vector<Usr> types;
std::vector<Usr> funcs;
std::vector<std::pair<Usr, int64_t>> vars;
2017-02-22 08:52:00 +00:00
// If set, then this is the same underlying type as the given value (ie, this
// type comes from a using or typedef statement).
Usr alias_of = 0;
2017-02-25 06:08:14 +00:00
int file_id = -1;
int16_t qual_name_offset = 0;
int16_t short_name_offset = 0;
int16_t short_name_size = 0;
lsSymbolKind kind = lsSymbolKind::Unknown;
std::vector<Usr> GetBases() const { return bases; }
2017-02-25 06:08:14 +00:00
};
2018-08-09 17:08:14 +00:00
MAKE_REFLECT_STRUCT(TypeDef, detailed_name, qual_name_offset, short_name_offset,
short_name_size, kind, hover, comments, spell, extent,
alias_of, bases, types, funcs, vars);
2017-02-25 06:08:14 +00:00
struct IndexType {
using Def = TypeDef;
2018-01-13 08:10:39 +00:00
Usr usr;
Def def;
std::vector<DeclRef> declarations;
std::vector<Use> uses;
std::vector<Usr> derived;
std::vector<Usr> instances;
2017-02-22 08:52:00 +00:00
};
2017-02-25 23:59:09 +00:00
struct VarDef : NameMixin<VarDef> {
2017-02-22 08:52:00 +00:00
// General metadata.
2018-08-09 17:08:14 +00:00
const char *detailed_name = "";
const char *hover = "";
const char *comments = "";
Maybe<Use> spell;
Maybe<Use> extent;
2017-02-22 08:52:00 +00:00
// Type of the variable.
Usr type = 0;
2017-02-22 08:52:00 +00:00
int file_id = -1;
int16_t qual_name_offset = 0;
int16_t short_name_offset = 0;
int16_t short_name_size = 0;
2017-02-22 08:52:00 +00:00
lsSymbolKind kind = lsSymbolKind::Unknown;
// Note a variable may have instances of both |None| and |Extern|
// (declaration).
uint8_t storage = clang::SC_None;
bool is_local() const {
return spell && spell->kind == SymbolKind::Func &&
storage == clang::SC_None;
}
std::vector<Usr> GetBases() const { return {}; }
2017-02-25 06:08:14 +00:00
};
2018-08-09 17:08:14 +00:00
MAKE_REFLECT_STRUCT(VarDef, detailed_name, qual_name_offset, short_name_offset,
short_name_size, hover, comments, spell, extent, type, kind,
storage);
2017-03-14 08:33:39 +00:00
struct IndexVar {
using Def = VarDef;
2018-01-13 08:10:39 +00:00
Usr usr;
Def def;
std::vector<DeclRef> declarations;
std::vector<Use> uses;
2017-02-25 23:59:09 +00:00
};
2017-05-21 03:46:15 +00:00
struct IndexInclude {
// Line that has the include directive. We don't have complete range
// information - a line is good enough for clicking.
int line = 0;
// Absolute path to the index.
const char *resolved_path;
2017-05-21 03:46:15 +00:00
};
2018-09-21 01:04:55 +00:00
namespace std {
template <> struct hash<llvm::sys::fs::UniqueID> {
std::size_t operator()(llvm::sys::fs::UniqueID ID) const {
size_t ret = ID.getDevice();
hash_combine(ret, ID.getFile());
return ret;
}
};
} // namespace std
struct IndexFile {
// For both JSON and MessagePack cache files.
static const int kMajorVersion;
// For MessagePack cache files.
// JSON has good forward compatibility because field addition/deletion do not
// harm but currently no efforts have been made to make old MessagePack cache
2018-03-31 03:16:33 +00:00
// files accepted by newer ccls.
static const int kMinorVersion;
2018-07-07 23:56:47 +00:00
llvm::sys::fs::UniqueID UniqueID;
2017-02-27 07:23:43 +00:00
std::string path;
2018-09-19 16:31:45 +00:00
std::vector<const char *> args;
// This is unfortunately time_t as used by clang::FileEntry
int64_t mtime = 0;
LanguageId language = LanguageId::C;
// uid2lid_and_path is used to generate lid2path, but not serialized.
std::unordered_map<llvm::sys::fs::UniqueID, std::pair<int, std::string>>
uid2lid_and_path;
std::vector<std::pair<int, std::string>> lid2path;
2017-04-20 07:25:38 +00:00
// The path to the translation unit cc file which caused the creation of this
// IndexFile. When parsing a translation unit we generate many IndexFile
2017-04-20 07:25:38 +00:00
// instances (ie, each header has a separate one). When the user edits a
// header we need to lookup the original translation unit and reindex that.
std::string import_file;
// Source ranges that were not processed.
std::vector<Range> skipped_ranges;
2017-05-21 03:46:15 +00:00
std::vector<IndexInclude> includes;
llvm::DenseMap<llvm::CachedHashStringRef, int64_t> dependencies;
std::unordered_map<Usr, IndexFunc> usr2func;
std::unordered_map<Usr, IndexType> usr2type;
std::unordered_map<Usr, IndexVar> usr2var;
2017-02-22 08:52:00 +00:00
2017-07-30 04:24:02 +00:00
// File contents at the time of index. Not serialized.
std::string file_contents;
2018-07-07 23:56:47 +00:00
IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path,
const std::string &contents);
2017-02-22 08:52:00 +00:00
2018-08-09 17:08:14 +00:00
IndexFunc &ToFunc(Usr usr);
IndexType &ToType(Usr usr);
IndexVar &ToVar(Usr usr);
2017-02-22 08:52:00 +00:00
std::string ToString();
};
struct CompletionManager;
struct WorkingFiles;
2018-09-21 01:04:55 +00:00
struct VFS;
2018-07-08 07:46:53 +00:00
namespace ccls::idx {
void Init();
2018-07-08 07:46:53 +00:00
std::vector<std::unique_ptr<IndexFile>>
Index(CompletionManager *complete, WorkingFiles *wfiles, VFS *vfs,
const std::string &opt_wdir, const std::string &file,
2018-09-19 16:31:45 +00:00
const std::vector<const char *> &args,
2018-09-23 01:00:50 +00:00
const std::vector<std::pair<std::string, std::string>> &remapped,
bool &ok);
} // namespace ccls::idx