// Copyright 2017-2018 ccls Authors // SPDX-License-Identifier: Apache-2.0 #pragma once #include "lsp.hh" #include "utils.hh" #include #include #include namespace ccls { struct WorkingFile { int version = 0; std::string filename; std::string buffer_content; // Note: This assumes 0-based lines (1-based lines are normally assumed). std::vector index_lines; // Note: This assumes 0-based lines (1-based lines are normally assumed). std::vector buffer_lines; // Mappings between index line number and buffer line number. // Empty indicates either buffer or index has been changed and re-computation // is required. // For index_to_buffer[i] == j, if j >= 0, we are confident that index line // i maps to buffer line j; if j == -1, FindMatchingLine will use the nearest // confident lines to resolve its line number. std::vector index_to_buffer; std::vector buffer_to_index; // A set of diagnostics that have been reported for this file. // NOTE: _ is appended because it must be accessed under the WorkingFiles // lock! std::vector diagnostics_; WorkingFile(const std::string &filename, const std::string &buffer_content); // This should be called when the indexed content has changed. void SetIndexContent(const std::string &index_content); // This should be called whenever |buffer_content| has changed. void OnBufferContentUpdated(); // Finds the buffer line number which maps to index line number |line|. // Also resolves |column| if not NULL. // When resolving a range, use is_end = false for begin() and is_end = // true for end() to get a better alignment of |column|. std::optional GetBufferPosFromIndexPos(int line, int *column, bool is_end); // Finds the index line number which maps to buffer line number |line|. // Also resolves |column| if not NULL. std::optional GetIndexPosFromBufferPos(int line, int *column, bool is_end); // Returns a relatively stable completion position (it jumps back until there // is a non-alphanumeric character). // // The out param |is_global_completion| is set to true if this looks like a // global completion. // The out param |existing_completion| is set to any existing completion // content the user has entered. Position FindStableCompletionSource(Position position, std::string *existing_completion, Position *replace_end_pos) const; private: // Compute index_to_buffer and buffer_to_index. void ComputeLineMapping(); }; struct WorkingFiles { struct Snapshot { struct File { std::string filename; std::string content; }; std::vector files; }; // // :: IMPORTANT :: All methods in this class are guarded by a single lock. // // Find the file with the given filename. WorkingFile *GetFileByFilename(const std::string &filename); WorkingFile *GetFileByFilenameNoLock(const std::string &filename); std::string GetContent(const std::string &filename); // Run |action| under the lock. template void DoAction(Fn &&fn) { std::lock_guard lock(files_mutex); fn(); } WorkingFile *OnOpen(const TextDocumentItem &open); void OnChange(const TextDocumentDidChangeParam &change); void OnClose(const TextDocumentIdentifier &close); // Use unique_ptrs so we can handout WorkingFile ptrs and not have them // invalidated if we resize files. std::vector> files; std::mutex files_mutex; // Protects |files|. }; int GetOffsetForPosition(Position pos, std::string_view content); std::string_view LexIdentifierAroundPos(Position position, std::string_view content); } // namespace ccls