mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-04 14:17:07 +00:00 
			
		
		
		
	.
This commit is contained in:
		
							parent
							
								
									6c8fee4141
								
							
						
					
					
						commit
						233e377137
					
				@ -96,6 +96,11 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
 | 
				
			|||||||
find_package(Threads REQUIRED)
 | 
					find_package(Threads REQUIRED)
 | 
				
			||||||
target_link_libraries(ccls PRIVATE Threads::Threads)
 | 
					target_link_libraries(ccls PRIVATE Threads::Threads)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
					  target_link_libraries(ccls PRIVATE -lstdc++fs)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
 | 
					if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
 | 
				
			||||||
  # loguru calls dladdr
 | 
					  # loguru calls dladdr
 | 
				
			||||||
  target_link_libraries(ccls PRIVATE ${CMAKE_DL_LIBS})
 | 
					  target_link_libraries(ccls PRIVATE ${CMAKE_DL_LIBS})
 | 
				
			||||||
@ -233,7 +238,6 @@ target_sources(ccls PRIVATE
 | 
				
			|||||||
               src/messages/text_document_did_open.cc
 | 
					               src/messages/text_document_did_open.cc
 | 
				
			||||||
               src/messages/text_document_did_save.cc
 | 
					               src/messages/text_document_did_save.cc
 | 
				
			||||||
               src/messages/text_document_document_highlight.cc
 | 
					               src/messages/text_document_document_highlight.cc
 | 
				
			||||||
               src/messages/text_document_document_link.cc
 | 
					 | 
				
			||||||
               src/messages/text_document_document_symbol.cc
 | 
					               src/messages/text_document_document_symbol.cc
 | 
				
			||||||
               src/messages/text_document_hover.cc
 | 
					               src/messages/text_document_hover.cc
 | 
				
			||||||
               src/messages/text_document_references.cc
 | 
					               src/messages/text_document_references.cc
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								src/filesystem.hh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/filesystem.hh
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <experimental/filesystem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace fs = std::experimental::filesystem;
 | 
				
			||||||
							
								
								
									
										110
									
								
								src/lex_utils.cc
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								src/lex_utils.cc
									
									
									
									
									
								
							@ -24,116 +24,6 @@ int GetOffsetForPosition(lsPosition position, std::string_view content) {
 | 
				
			|||||||
  return int(i);
 | 
					  return int(i);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: eliminate |line_number| param.
 | 
					 | 
				
			||||||
std::optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line) {
 | 
					 | 
				
			||||||
  // Find starting and ending quote.
 | 
					 | 
				
			||||||
  int start = 0;
 | 
					 | 
				
			||||||
  while (start < (int)line.size()) {
 | 
					 | 
				
			||||||
    char c = line[start];
 | 
					 | 
				
			||||||
    ++start;
 | 
					 | 
				
			||||||
    if (c == '"' || c == '<')
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (start == (int)line.size())
 | 
					 | 
				
			||||||
    return std::nullopt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int end = (int)line.size();
 | 
					 | 
				
			||||||
  while (end > 0) {
 | 
					 | 
				
			||||||
    char c = line[end];
 | 
					 | 
				
			||||||
    if (c == '"' || c == '>')
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    --end;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (start >= end)
 | 
					 | 
				
			||||||
    return std::nullopt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return lsRange(lsPosition(line_number, start), lsPosition(line_number, end));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void LexFunctionDeclaration(const std::string& buffer_content,
 | 
					 | 
				
			||||||
                            lsPosition declaration_spelling,
 | 
					 | 
				
			||||||
                            std::optional<std::string> type_name,
 | 
					 | 
				
			||||||
                            std::string* insert_text,
 | 
					 | 
				
			||||||
                            int* newlines_after_name) {
 | 
					 | 
				
			||||||
  int name_start = GetOffsetForPosition(declaration_spelling, buffer_content);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool parse_return_type = true;
 | 
					 | 
				
			||||||
  // We need to check if we have a return type (ctors and dtors do not).
 | 
					 | 
				
			||||||
  if (type_name) {
 | 
					 | 
				
			||||||
    int name_end = name_start;
 | 
					 | 
				
			||||||
    while (name_end < buffer_content.size()) {
 | 
					 | 
				
			||||||
      char c = buffer_content[name_end];
 | 
					 | 
				
			||||||
      if (isspace(c) || c == '(')
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      ++name_end;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::string func_name =
 | 
					 | 
				
			||||||
        buffer_content.substr(name_start, name_end - name_start);
 | 
					 | 
				
			||||||
    if (func_name == *type_name || func_name == ("~" + *type_name))
 | 
					 | 
				
			||||||
      parse_return_type = false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // We need to fetch the return type. This can get complex, ie,
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
  //  std::vector <int> foo();
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
  int return_start = name_start;
 | 
					 | 
				
			||||||
  if (parse_return_type) {
 | 
					 | 
				
			||||||
    int paren_balance = 0;
 | 
					 | 
				
			||||||
    int angle_balance = 0;
 | 
					 | 
				
			||||||
    bool expect_token = true;
 | 
					 | 
				
			||||||
    while (return_start > 0) {
 | 
					 | 
				
			||||||
      char c = buffer_content[return_start - 1];
 | 
					 | 
				
			||||||
      if (paren_balance == 0 && angle_balance == 0) {
 | 
					 | 
				
			||||||
        if (isspace(c) && !expect_token) {
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (!isspace(c))
 | 
					 | 
				
			||||||
          expect_token = false;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (c == ')')
 | 
					 | 
				
			||||||
        ++paren_balance;
 | 
					 | 
				
			||||||
      if (c == '(') {
 | 
					 | 
				
			||||||
        --paren_balance;
 | 
					 | 
				
			||||||
        expect_token = true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (c == '>')
 | 
					 | 
				
			||||||
        ++angle_balance;
 | 
					 | 
				
			||||||
      if (c == '<') {
 | 
					 | 
				
			||||||
        --angle_balance;
 | 
					 | 
				
			||||||
        expect_token = true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return_start -= 1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // We need to fetch the arguments. Just scan for the next ';'.
 | 
					 | 
				
			||||||
  *newlines_after_name = 0;
 | 
					 | 
				
			||||||
  int end = name_start;
 | 
					 | 
				
			||||||
  while (end < buffer_content.size()) {
 | 
					 | 
				
			||||||
    char c = buffer_content[end];
 | 
					 | 
				
			||||||
    if (c == ';')
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    if (c == '\n')
 | 
					 | 
				
			||||||
      *newlines_after_name += 1;
 | 
					 | 
				
			||||||
    ++end;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  std::string result;
 | 
					 | 
				
			||||||
  result += buffer_content.substr(return_start, name_start - return_start);
 | 
					 | 
				
			||||||
  if (type_name && !type_name->empty())
 | 
					 | 
				
			||||||
    result += *type_name + "::";
 | 
					 | 
				
			||||||
  result += buffer_content.substr(name_start, end - name_start);
 | 
					 | 
				
			||||||
  TrimEndInPlace(result);
 | 
					 | 
				
			||||||
  result += " {\n}";
 | 
					 | 
				
			||||||
  *insert_text = result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
					std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
				
			||||||
                                        std::string_view content) {
 | 
					                                        std::string_view content) {
 | 
				
			||||||
  int start = GetOffsetForPosition(position, content);
 | 
					  int start = GetOffsetForPosition(position, content);
 | 
				
			||||||
 | 
				
			|||||||
@ -3,22 +3,11 @@
 | 
				
			|||||||
#include "lsp.h"
 | 
					#include "lsp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string_view>
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <string>
 | 
					 | 
				
			||||||
#include <tuple>
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Utility method to map |position| to an offset inside of |content|.
 | 
					// Utility method to map |position| to an offset inside of |content|.
 | 
				
			||||||
int GetOffsetForPosition(lsPosition position, std::string_view content);
 | 
					int GetOffsetForPosition(lsPosition position, std::string_view content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: eliminate |line_number| param.
 | 
					 | 
				
			||||||
std::optional<lsRange> ExtractQuotedRange(int line_number, const std::string& line);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void LexFunctionDeclaration(const std::string& buffer_content,
 | 
					 | 
				
			||||||
                            lsPosition declaration_spelling,
 | 
					 | 
				
			||||||
                            std::optional<std::string> type_name,
 | 
					 | 
				
			||||||
                            std::string* insert_text,
 | 
					 | 
				
			||||||
                            int* newlines_after_name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
					std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
				
			||||||
                                        std::string_view content);
 | 
					                                        std::string_view content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,85 +0,0 @@
 | 
				
			|||||||
#include "lex_utils.h"
 | 
					 | 
				
			||||||
#include "message_handler.h"
 | 
					 | 
				
			||||||
#include "queue_manager.h"
 | 
					 | 
				
			||||||
#include "working_files.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <loguru.hpp>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace {
 | 
					 | 
				
			||||||
MethodType kMethodType = "textDocument/documentLink";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct In_TextDocumentDocumentLink : public RequestInMessage {
 | 
					 | 
				
			||||||
  MethodType GetMethodType() const override { return kMethodType; }
 | 
					 | 
				
			||||||
  struct Params {
 | 
					 | 
				
			||||||
    // The document to provide document links for.
 | 
					 | 
				
			||||||
    lsTextDocumentIdentifier textDocument;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  Params params;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentLink::Params, textDocument);
 | 
					 | 
				
			||||||
MAKE_REFLECT_STRUCT(In_TextDocumentDocumentLink, id, params);
 | 
					 | 
				
			||||||
REGISTER_IN_MESSAGE(In_TextDocumentDocumentLink);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// A document link is a range in a text document that links to an internal or
 | 
					 | 
				
			||||||
// external resource, like another text document or a web site.
 | 
					 | 
				
			||||||
struct lsDocumentLink {
 | 
					 | 
				
			||||||
  // The range this link applies to.
 | 
					 | 
				
			||||||
  lsRange range;
 | 
					 | 
				
			||||||
  // The uri this link points to. If missing a resolve request is sent later.
 | 
					 | 
				
			||||||
  std::optional<lsDocumentUri> target;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
MAKE_REFLECT_STRUCT(lsDocumentLink, range, target);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Out_TextDocumentDocumentLink
 | 
					 | 
				
			||||||
    : public lsOutMessage<Out_TextDocumentDocumentLink> {
 | 
					 | 
				
			||||||
  lsRequestId id;
 | 
					 | 
				
			||||||
  std::vector<lsDocumentLink> result;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentLink, jsonrpc, id, result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Handler_TextDocumentDocumentLink
 | 
					 | 
				
			||||||
    : BaseMessageHandler<In_TextDocumentDocumentLink> {
 | 
					 | 
				
			||||||
  MethodType GetMethodType() const override { return kMethodType; }
 | 
					 | 
				
			||||||
  void Run(In_TextDocumentDocumentLink* request) override {
 | 
					 | 
				
			||||||
    Out_TextDocumentDocumentLink out;
 | 
					 | 
				
			||||||
    out.id = request->id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (config->showDocumentLinksOnIncludes) {
 | 
					 | 
				
			||||||
      QueryFile* file;
 | 
					 | 
				
			||||||
      if (!FindFileOrFail(db, project, request->id,
 | 
					 | 
				
			||||||
                          request->params.textDocument.uri.GetPath(), &file)) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      WorkingFile* working_file = working_files->GetFileByFilename(
 | 
					 | 
				
			||||||
          request->params.textDocument.uri.GetPath());
 | 
					 | 
				
			||||||
      if (!working_file) {
 | 
					 | 
				
			||||||
        LOG_S(WARNING) << "Unable to find working file "
 | 
					 | 
				
			||||||
                       << request->params.textDocument.uri.GetPath();
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      for (const IndexInclude& include : file->def->includes) {
 | 
					 | 
				
			||||||
        std::optional<int> buffer_line = working_file->GetBufferPosFromIndexPos(
 | 
					 | 
				
			||||||
            include.line, nullptr, false);
 | 
					 | 
				
			||||||
        if (!buffer_line)
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Subtract 1 from line because querydb stores 1-based lines but
 | 
					 | 
				
			||||||
        // vscode expects 0-based lines.
 | 
					 | 
				
			||||||
        std::optional<lsRange> between_quotes = ExtractQuotedRange(
 | 
					 | 
				
			||||||
            *buffer_line, working_file->buffer_lines[*buffer_line]);
 | 
					 | 
				
			||||||
        if (!between_quotes)
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        lsDocumentLink link;
 | 
					 | 
				
			||||||
        link.target = lsDocumentUri::FromPath(include.resolved_path);
 | 
					 | 
				
			||||||
        link.range = *between_quotes;
 | 
					 | 
				
			||||||
        out.result.push_back(link);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    QueueManager::WriteStdout(kMethodType, out);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDocumentLink);
 | 
					 | 
				
			||||||
}  // namespace
 | 
					 | 
				
			||||||
@ -292,7 +292,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
 | 
				
			|||||||
std::vector<std::string> ReadCompilerArgumentsFromFile(
 | 
					std::vector<std::string> ReadCompilerArgumentsFromFile(
 | 
				
			||||||
    const std::string& path) {
 | 
					    const std::string& path) {
 | 
				
			||||||
  std::vector<std::string> args;
 | 
					  std::vector<std::string> args;
 | 
				
			||||||
  for (std::string line : ReadLinesWithEnding(path)) {
 | 
					  for (std::string line : ReadFileLines(path)) {
 | 
				
			||||||
    TrimInPlace(line);
 | 
					    TrimInPlace(line);
 | 
				
			||||||
    if (line.empty() || StartsWith(line, "#"))
 | 
					    if (line.empty() || StartsWith(line, "#"))
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
 | 
				
			|||||||
@ -343,7 +343,7 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
 | 
				
			|||||||
      std::cout << "Running " << path << std::endl;
 | 
					      std::cout << "Running " << path << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Parse expected output from the test, parse it into JSON document.
 | 
					    // Parse expected output from the test, parse it into JSON document.
 | 
				
			||||||
    std::vector<std::string> lines_with_endings = ReadLinesWithEnding(path);
 | 
					    std::vector<std::string> lines_with_endings = ReadFileLines(path);
 | 
				
			||||||
    TextReplacer text_replacer;
 | 
					    TextReplacer text_replacer;
 | 
				
			||||||
    std::vector<std::string> flags;
 | 
					    std::vector<std::string> flags;
 | 
				
			||||||
    std::unordered_map<std::string, std::string> all_expected_output;
 | 
					    std::unordered_map<std::string, std::string> all_expected_output;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										140
									
								
								src/utils.cc
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								src/utils.cc
									
									
									
									
									
								
							@ -1,10 +1,10 @@
 | 
				
			|||||||
#include "utils.h"
 | 
					#include "utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "filesystem.hh"
 | 
				
			||||||
#include "platform.h"
 | 
					#include "platform.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <doctest/doctest.h>
 | 
					#include <doctest/doctest.h>
 | 
				
			||||||
#include <siphash.h>
 | 
					#include <siphash.h>
 | 
				
			||||||
#include <tinydir.h>
 | 
					 | 
				
			||||||
#include <loguru/loguru.hpp>
 | 
					#include <loguru/loguru.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
@ -18,10 +18,6 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__APPLE__)
 | 
					 | 
				
			||||||
#include <sparsepp/spp_memory.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DEFAULT_RESOURCE_DIRECTORY is passed with quotes for non-MSVC compilers, ie,
 | 
					// DEFAULT_RESOURCE_DIRECTORY is passed with quotes for non-MSVC compilers, ie,
 | 
				
			||||||
// foo vs "foo".
 | 
					// foo vs "foo".
 | 
				
			||||||
#if defined(_MSC_VER)
 | 
					#if defined(_MSC_VER)
 | 
				
			||||||
@ -31,22 +27,15 @@
 | 
				
			|||||||
#define ENSURE_STRING_MACRO_ARGUMENT(x) x
 | 
					#define ENSURE_STRING_MACRO_ARGUMENT(x) x
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// See http://stackoverflow.com/a/217605
 | 
					void TrimInPlace(std::string& s) {
 | 
				
			||||||
void TrimStartInPlace(std::string& s) {
 | 
					 | 
				
			||||||
  s.erase(s.begin(),
 | 
					  s.erase(s.begin(),
 | 
				
			||||||
          std::find_if(s.begin(), s.end(),
 | 
					          std::find_if(s.begin(), s.end(),
 | 
				
			||||||
                       std::not1(std::ptr_fun<int, int>(std::isspace))));
 | 
					                       std::not1(std::ptr_fun<int, int>(std::isspace))));
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void TrimEndInPlace(std::string& s) {
 | 
					 | 
				
			||||||
  s.erase(std::find_if(s.rbegin(), s.rend(),
 | 
					  s.erase(std::find_if(s.rbegin(), s.rend(),
 | 
				
			||||||
                       std::not1(std::ptr_fun<int, int>(std::isspace)))
 | 
					                       std::not1(std::ptr_fun<int, int>(std::isspace)))
 | 
				
			||||||
              .base(),
 | 
					              .base(),
 | 
				
			||||||
          s.end());
 | 
					          s.end());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void TrimInPlace(std::string& s) {
 | 
					 | 
				
			||||||
  TrimStartInPlace(s);
 | 
					 | 
				
			||||||
  TrimEndInPlace(s);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
std::string Trim(std::string s) {
 | 
					std::string Trim(std::string s) {
 | 
				
			||||||
  TrimInPlace(s);
 | 
					  TrimInPlace(s);
 | 
				
			||||||
  return s;
 | 
					  return s;
 | 
				
			||||||
@ -138,32 +127,8 @@ std::string GetBaseName(const std::string& path) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string StripFileType(const std::string& path) {
 | 
					std::string StripFileType(const std::string& path) {
 | 
				
			||||||
  size_t last_period = path.find_last_of('.');
 | 
					  fs::path p(path);
 | 
				
			||||||
  if (last_period != std::string::npos)
 | 
					  return p.parent_path() / p.stem();
 | 
				
			||||||
    return path.substr(0, last_period);
 | 
					 | 
				
			||||||
  return path;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// See http://stackoverflow.com/a/29752943
 | 
					 | 
				
			||||||
std::string ReplaceAll(const std::string& source,
 | 
					 | 
				
			||||||
                       const std::string& from,
 | 
					 | 
				
			||||||
                       const std::string& to) {
 | 
					 | 
				
			||||||
  std::string result;
 | 
					 | 
				
			||||||
  result.reserve(source.length());  // avoids a few memory allocations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  std::string::size_type last_pos = 0;
 | 
					 | 
				
			||||||
  std::string::size_type find_pos;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  while (std::string::npos != (find_pos = source.find(from, last_pos))) {
 | 
					 | 
				
			||||||
    result.append(source, last_pos, find_pos - last_pos);
 | 
					 | 
				
			||||||
    result += to;
 | 
					 | 
				
			||||||
    last_pos = find_pos + from.length();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Care for the rest after last occurrence
 | 
					 | 
				
			||||||
  result += source.substr(last_pos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return result;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<std::string> SplitString(const std::string& str,
 | 
					std::vector<std::string> SplitString(const std::string& str,
 | 
				
			||||||
@ -198,51 +163,25 @@ static void GetFilesInFolderHelper(
 | 
				
			|||||||
    bool recursive,
 | 
					    bool recursive,
 | 
				
			||||||
    std::string output_prefix,
 | 
					    std::string output_prefix,
 | 
				
			||||||
    const std::function<void(const std::string&)>& handler) {
 | 
					    const std::function<void(const std::string&)>& handler) {
 | 
				
			||||||
  std::queue<std::pair<std::string, std::string>> q;
 | 
					  std::queue<std::pair<fs::path, fs::path>> q;
 | 
				
			||||||
  q.push(make_pair(folder, output_prefix));
 | 
					  q.push(std::make_pair(fs::path(folder), fs::path(output_prefix)));
 | 
				
			||||||
  while (!q.empty()) {
 | 
					  while (!q.empty()) {
 | 
				
			||||||
    tinydir_dir dir;
 | 
					    for (auto it = fs::directory_iterator(q.front().first); it != fs::directory_iterator(); ++it) {
 | 
				
			||||||
    if (tinydir_open(&dir, q.front().first.c_str()) == -1) {
 | 
					      auto path = it->path();
 | 
				
			||||||
      LOG_S(WARNING) << "Unable to open directory " << folder;
 | 
					      std::string filename = path.filename();
 | 
				
			||||||
      goto bail;
 | 
					      if (filename[0] != '.' || filename == ".ccls") {
 | 
				
			||||||
    }
 | 
					        fs::file_status status = it->symlink_status();
 | 
				
			||||||
 | 
					        if (fs::is_regular_file(status))
 | 
				
			||||||
    while (dir.has_next) {
 | 
					          handler(q.front().second / filename);
 | 
				
			||||||
      tinydir_file file;
 | 
					        else if (fs::is_directory(status) || fs::is_symlink(status)) {
 | 
				
			||||||
      if (tinydir_readfile(&dir, &file) == -1) {
 | 
					 | 
				
			||||||
        LOG_S(WARNING) << "Unable to read file " << file.name
 | 
					 | 
				
			||||||
                       << " when reading directory " << folder;
 | 
					 | 
				
			||||||
        goto bail;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Skip all dot files except .ccls.
 | 
					 | 
				
			||||||
      //
 | 
					 | 
				
			||||||
      // The nested ifs are intentional, branching order is subtle here.
 | 
					 | 
				
			||||||
      //
 | 
					 | 
				
			||||||
      // Note that in the future if we do support dot directories/files, we must
 | 
					 | 
				
			||||||
      // always ignore the '.' and '..' directories otherwise this will loop
 | 
					 | 
				
			||||||
      // infinitely.
 | 
					 | 
				
			||||||
      if (file.name[0] != '.' || strcmp(file.name, ".ccls") == 0) {
 | 
					 | 
				
			||||||
        if (file.is_dir) {
 | 
					 | 
				
			||||||
          if (recursive) {
 | 
					          if (recursive) {
 | 
				
			||||||
            std::string child_dir = q.front().second + file.name + "/";
 | 
					            std::string child_dir = q.front().second / filename;
 | 
				
			||||||
            if (!IsSymLink(file.path))
 | 
					            if (fs::is_directory(status))
 | 
				
			||||||
              q.push(make_pair(file.path, child_dir));
 | 
					              q.push(make_pair(path, child_dir));
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          handler(q.front().second + file.name);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (tinydir_next(&dir) == -1) {
 | 
					 | 
				
			||||||
        LOG_S(WARNING) << "Unable to fetch next file when reading directory "
 | 
					 | 
				
			||||||
                       << folder;
 | 
					 | 
				
			||||||
        goto bail;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  bail:
 | 
					 | 
				
			||||||
    tinydir_close(&dir);
 | 
					 | 
				
			||||||
    q.pop();
 | 
					    q.pop();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -311,8 +250,7 @@ std::istream& SafeGetline(std::istream& is, std::string& t) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool FileExists(const std::string& filename) {
 | 
					bool FileExists(const std::string& filename) {
 | 
				
			||||||
  std::ifstream cache(filename);
 | 
					  return fs::exists(filename);
 | 
				
			||||||
  return cache.is_open();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::optional<std::string> ReadContent(const std::string& filename) {
 | 
					std::optional<std::string> ReadContent(const std::string& filename) {
 | 
				
			||||||
@ -328,31 +266,20 @@ std::optional<std::string> ReadContent(const std::string& filename) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<std::string> ReadLinesWithEnding(std::string filename) {
 | 
					std::vector<std::string> ReadFileLines(std::string filename) {
 | 
				
			||||||
  std::vector<std::string> result;
 | 
					  std::vector<std::string> result;
 | 
				
			||||||
 | 
					  std::ifstream fin(filename);
 | 
				
			||||||
  std::ifstream input(filename);
 | 
					  for (std::string line; std::getline(fin, line);)
 | 
				
			||||||
  for (std::string line; SafeGetline(input, line);)
 | 
					 | 
				
			||||||
    result.push_back(line);
 | 
					    result.push_back(line);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<std::string> ToLines(const std::string& content,
 | 
					std::vector<std::string> ToLines(const std::string& content) {
 | 
				
			||||||
                                 bool trim_whitespace) {
 | 
					 | 
				
			||||||
  std::vector<std::string> result;
 | 
					  std::vector<std::string> result;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  std::istringstream lines(content);
 | 
					  std::istringstream lines(content);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  std::string line;
 | 
					  std::string line;
 | 
				
			||||||
  while (getline(lines, line)) {
 | 
					  while (getline(lines, line))
 | 
				
			||||||
    if (trim_whitespace)
 | 
					 | 
				
			||||||
      TrimInPlace(line);
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      RemoveLastCR(line);
 | 
					 | 
				
			||||||
    result.push_back(line);
 | 
					    result.push_back(line);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -385,27 +312,6 @@ void WriteToFile(const std::string& filename, const std::string& content) {
 | 
				
			|||||||
  file << content;
 | 
					  file << content;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float GetProcessMemoryUsedInMb() {
 | 
					 | 
				
			||||||
#if defined(__APPLE__)
 | 
					 | 
				
			||||||
  return 0.f;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
  const float kBytesToMb = 1000000;
 | 
					 | 
				
			||||||
  uint64_t memory_after = spp::GetProcessMemoryUsed();
 | 
					 | 
				
			||||||
  return memory_after / kBytesToMb;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string FormatMicroseconds(long long microseconds) {
 | 
					 | 
				
			||||||
  long long milliseconds = microseconds / 1000;
 | 
					 | 
				
			||||||
  long long remaining = microseconds - milliseconds;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Only show two digits after the dot.
 | 
					 | 
				
			||||||
  while (remaining >= 100)
 | 
					 | 
				
			||||||
    remaining /= 10;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return std::to_string(milliseconds) + "." + std::to_string(remaining) + "ms";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string GetDefaultResourceDirectory() {
 | 
					std::string GetDefaultResourceDirectory() {
 | 
				
			||||||
  std::string result;
 | 
					  std::string result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								src/utils.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/utils.h
									
									
									
									
									
								
							@ -10,11 +10,6 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Trim from start (in place)
 | 
					 | 
				
			||||||
void TrimStartInPlace(std::string& s);
 | 
					 | 
				
			||||||
// Trim from end (in place)
 | 
					 | 
				
			||||||
void TrimEndInPlace(std::string& s);
 | 
					 | 
				
			||||||
// Trim from both ends (in place)
 | 
					 | 
				
			||||||
void TrimInPlace(std::string& s);
 | 
					void TrimInPlace(std::string& s);
 | 
				
			||||||
std::string Trim(std::string s);
 | 
					std::string Trim(std::string s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,10 +36,6 @@ std::string GetBaseName(const std::string& path);
 | 
				
			|||||||
// Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar".
 | 
					// Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar".
 | 
				
			||||||
std::string StripFileType(const std::string& path);
 | 
					std::string StripFileType(const std::string& path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string ReplaceAll(const std::string& source,
 | 
					 | 
				
			||||||
                       const std::string& from,
 | 
					 | 
				
			||||||
                       const std::string& to);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::vector<std::string> SplitString(const std::string& str,
 | 
					std::vector<std::string> SplitString(const std::string& str,
 | 
				
			||||||
                                     const std::string& delimiter);
 | 
					                                     const std::string& delimiter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -95,9 +86,8 @@ std::string EscapeFileName(std::string path);
 | 
				
			|||||||
// FIXME: Move ReadContent into ICacheManager?
 | 
					// FIXME: Move ReadContent into ICacheManager?
 | 
				
			||||||
bool FileExists(const std::string& filename);
 | 
					bool FileExists(const std::string& filename);
 | 
				
			||||||
std::optional<std::string> ReadContent(const std::string& filename);
 | 
					std::optional<std::string> ReadContent(const std::string& filename);
 | 
				
			||||||
std::vector<std::string> ReadLinesWithEnding(std::string filename);
 | 
					std::vector<std::string> ReadFileLines(std::string filename);
 | 
				
			||||||
std::vector<std::string> ToLines(const std::string& content,
 | 
					std::vector<std::string> ToLines(const std::string& content);
 | 
				
			||||||
                                 bool trim_whitespace);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TextReplacer {
 | 
					struct TextReplacer {
 | 
				
			||||||
  struct Replacement {
 | 
					  struct Replacement {
 | 
				
			||||||
@ -163,11 +153,4 @@ inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
 | 
				
			|||||||
  };                                              \
 | 
					  };                                              \
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float GetProcessMemoryUsedInMb();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string FormatMicroseconds(long long microseconds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::string GetDefaultResourceDirectory();
 | 
					std::string GetDefaultResourceDirectory();
 | 
				
			||||||
 | 
					 | 
				
			||||||
// Makes sure all newlines in |output| are in \r\n format.
 | 
					 | 
				
			||||||
std::string UpdateToRnNewlines(std::string output);
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -215,14 +215,14 @@ WorkingFile::WorkingFile(const std::string& filename,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WorkingFile::SetIndexContent(const std::string& index_content) {
 | 
					void WorkingFile::SetIndexContent(const std::string& index_content) {
 | 
				
			||||||
  index_lines = ToLines(index_content, false /*trim_whitespace*/);
 | 
					  index_lines = ToLines(index_content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  index_to_buffer.clear();
 | 
					  index_to_buffer.clear();
 | 
				
			||||||
  buffer_to_index.clear();
 | 
					  buffer_to_index.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WorkingFile::OnBufferContentUpdated() {
 | 
					void WorkingFile::OnBufferContentUpdated() {
 | 
				
			||||||
  buffer_lines = ToLines(buffer_content, false /*trim_whitespace*/);
 | 
					  buffer_lines = ToLines(buffer_content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  index_to_buffer.clear();
 | 
					  index_to_buffer.clear();
 | 
				
			||||||
  buffer_to_index.clear();
 | 
					  buffer_to_index.clear();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user