#pragma once #include "language_server_api.h" #include "utils.h" #include #include #include #include using std::experimental::optional; using std::experimental::nullopt; // Utility method to map |position| to an offset inside of |content|. int GetOffsetForPosition(lsPosition position, const std::string& content); // Utility method to find a position for the given character. lsPosition CharPos(const std::string& search, char character, int character_offset = 0); 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 all_buffer_lines; // This map goes from disk-line -> indicies+1 in index_lines. // Note: The items in the value entry are 1-based lines. std::unordered_map> index_lines_lookup; // This map goes from buffer-line -> indices+1 in all_buffer_lines. // Note: The items in the value entry are 1-based liness. std::unordered_map> all_buffer_lines_lookup; // 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(); // Find the buffer-line which should be shown for |indexed_line|. This // accepts and returns 1-based lines. optional GetBufferLineFromIndexLine(int indexed_line) const; // Find the indexed-line which should be shown for |buffer_line|. This // accepts and returns 1-based lines. optional GetIndexLineFromBufferLine(int buffer_line) const; optional GetBufferLineContentFromIndexLine(int indexed_line, optional* out_buffer_line) const; // Finds the closest 'callable' name prior to position. This is used for // signature help to filter code completion results. // // |completion_position| will be point to a good code completion location to // for fetching signatures. std::string FindClosestCallNameInBuffer(lsPosition position, int* active_parameter, lsPosition* completion_position = nullptr) const; // 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. lsPosition FindStableCompletionSource(lsPosition position, bool* is_global_completion) const; CXUnsavedFile AsUnsavedFile() const; }; struct WorkingFiles { // // :: 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); // Run |action| under the lock. void DoAction(const std::function& action); // Run |action| on the file identified by |filename|. This executes under the lock. void DoActionOnFile(const std::string& filename, const std::function& action); WorkingFile* OnOpen(const Ipc_TextDocumentDidOpen::Params& open); void OnChange(const Ipc_TextDocumentDidChange::Params& change); void OnClose(const Ipc_TextDocumentDidClose::Params& close); std::vector AsUnsavedFiles(); // 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|. };