Index: clangd/index/Index.h =================================================================== --- clangd/index/Index.h +++ clangd/index/Index.h @@ -33,10 +33,17 @@ struct SymbolLocation { // Specify a position (Line, Column) of symbol. Using Line/Column allows us to // build LSP responses without reading the file content. + // + // Position is encoded as a 32-bits integer like below: + // |<--- 20 bits --->|<-12 bits->| + // |<--- Line --->|<- Column->| struct Position { - uint32_t Line = 0; // 0-based + static constexpr int LineBits = 20; + static constexpr int ColumnBits = 12; + + uint32_t Line : LineBits; // 0-based // Using UTF-16 code units. - uint32_t Column = 0; // 0-based + uint32_t Column : ColumnBits; // 0-based }; // The URI of the source file where a symbol occurs. Index: clangd/index/YAMLSerialization.cpp =================================================================== --- clangd/index/YAMLSerialization.cpp +++ clangd/index/YAMLSerialization.cpp @@ -94,18 +94,37 @@ uint8_t Origin = 0; }; -template <> struct MappingTraits { - static void mapping(IO &IO, SymbolLocation::Position &Value) { - IO.mapRequired("Line", Value.Line); - IO.mapRequired("Column", Value.Column); +struct NormalizedPosition { + using Position = clang::clangd::SymbolLocation::Position; + NormalizedPosition(IO &) {} + NormalizedPosition(IO &, const Position &Pos) { + static_assert( + sizeof(Position) == sizeof(uint32_t), + "SymbolLocation::Position structure can not fit into a uint32_t."); + value = (Pos.Line << Position::ColumnBits) + Pos.Column; } + + Position denormalize(IO &) { + Position Pos; + Pos.Line = value >> Position::ColumnBits; + Pos.Column = value & ((1 << Position::ColumnBits) - 1); + return Pos; + } + + // Encode the SymbolLocation::Position: + // | Line | Column | + uint32_t value; }; template <> struct MappingTraits { static void mapping(IO &IO, SymbolLocation &Value) { IO.mapRequired("FileURI", Value.FileURI); - IO.mapRequired("Start", Value.Start); - IO.mapRequired("End", Value.End); + MappingNormalization NStart( + IO, Value.Start); + IO.mapRequired("Start", NStart->value); + MappingNormalization NEnd( + IO, Value.End); + IO.mapRequired("End", NEnd->value); } }; Index: unittests/clangd/FileIndexTests.cpp =================================================================== --- unittests/clangd/FileIndexTests.cpp +++ unittests/clangd/FileIndexTests.cpp @@ -32,10 +32,10 @@ using testing::UnorderedElementsAre; MATCHER_P(RefRange, Range, "") { - return std::tie(arg.Location.Start.Line, arg.Location.Start.Column, - arg.Location.End.Line, arg.Location.End.Column) == - std::tie(Range.start.line, Range.start.character, Range.end.line, - Range.end.character); + return arg.Location.Start.Line == Range.start.line && + arg.Location.Start.Column == Range.start.character && + arg.Location.End.Line == Range.end.line && + arg.Location.End.Column == Range.end.character; } MATCHER_P(FileURI, F, "") { return arg.Location.FileURI == F; } MATCHER_P(DeclURI, U, "") { return arg.CanonicalDeclaration.FileURI == U; } Index: unittests/clangd/SerializationTests.cpp =================================================================== --- unittests/clangd/SerializationTests.cpp +++ unittests/clangd/SerializationTests.cpp @@ -33,12 +33,8 @@ Lang: Cpp CanonicalDeclaration: FileURI: file:///path/foo.h - Start: - Line: 1 - Column: 0 - End: - Line: 1 - Column: 1 + Start: 4096 # Line 1, Column 0 + End: 4097 # Line 1, Column 1 Origin: 4 Flags: 1 Documentation: 'Foo doc' @@ -59,12 +55,8 @@ Lang: Cpp CanonicalDeclaration: FileURI: file:///path/bar.h - Start: - Line: 1 - Column: 0 - End: - Line: 1 - Column: 1 + Start: 4096 # Line 1, Column 0 + End: 4097 # Line 1, Column 1 Flags: 2 Signature: '-sig' CompletionSnippetSuffix: '-snippet' @@ -75,12 +67,8 @@ - Kind: 4 Location: FileURI: file:///path/foo.cc - Start: - Line: 5 - Column: 3 - End: - Line: 5 - Column: 8 + Start: 20483 # Line 5, Column 3 + End: 20485 # Line5, Column 8 )"; MATCHER_P(ID, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }