mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-03 22:04:24 +00:00 
			
		
		
		
	Remove WithFileContent & lex_utils.{cc,h}
This commit is contained in:
		
							parent
							
								
									ec00f854a0
								
							
						
					
					
						commit
						39a17a9fd7
					
				@ -202,7 +202,6 @@ target_sources(ccls PRIVATE
 | 
			
		||||
               src/indexer.cc
 | 
			
		||||
               src/method.cc
 | 
			
		||||
               src/language.cc
 | 
			
		||||
               src/lex_utils.cc
 | 
			
		||||
               src/log.cc
 | 
			
		||||
               src/lsp.cc
 | 
			
		||||
               src/match.cc
 | 
			
		||||
 | 
			
		||||
@ -3,9 +3,11 @@
 | 
			
		||||
#include "log.hh"
 | 
			
		||||
#include "platform.h"
 | 
			
		||||
#include "serializer.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "type_printer.h"
 | 
			
		||||
 | 
			
		||||
#include <llvm/Support/Timer.h>
 | 
			
		||||
using namespace llvm;
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
@ -2016,7 +2018,8 @@ std::vector<std::unique_ptr<IndexFile>> ClangIndexer::Index(
 | 
			
		||||
 | 
			
		||||
  file = NormalizePath(file);
 | 
			
		||||
 | 
			
		||||
  Timer timer;
 | 
			
		||||
  Timer timer("parse", "parse tu");
 | 
			
		||||
  timer.startTimer();
 | 
			
		||||
 | 
			
		||||
  std::vector<CXUnsavedFile> unsaved_files;
 | 
			
		||||
  for (const FileContents& contents : file_contents) {
 | 
			
		||||
@ -2034,7 +2037,7 @@ std::vector<std::unique_ptr<IndexFile>> ClangIndexer::Index(
 | 
			
		||||
  if (!tu)
 | 
			
		||||
    return {};
 | 
			
		||||
 | 
			
		||||
  perf->index_parse = timer.ElapsedMicrosecondsAndReset();
 | 
			
		||||
  timer.stopTimer();
 | 
			
		||||
 | 
			
		||||
  return ParseWithTu(vfs, perf, tu.get(), &index, file, args, unsaved_files);
 | 
			
		||||
}
 | 
			
		||||
@ -2048,6 +2051,7 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
 | 
			
		||||
    const std::vector<std::string>& args,
 | 
			
		||||
    const std::vector<CXUnsavedFile>& file_contents) {
 | 
			
		||||
  Timer timer;
 | 
			
		||||
  timer.startTimer();
 | 
			
		||||
 | 
			
		||||
  IndexerCallbacks callback = {0};
 | 
			
		||||
  // Available callbacks:
 | 
			
		||||
@ -2085,13 +2089,12 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
 | 
			
		||||
                 << " failed with errno=" << index_result;
 | 
			
		||||
    return {};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clang_IndexAction_dispose(index_action);
 | 
			
		||||
 | 
			
		||||
  ClangCursor(clang_getTranslationUnitCursor(tu->cx_tu))
 | 
			
		||||
      .VisitChildren(&VisitMacroDefinitionAndExpansions, ¶m);
 | 
			
		||||
 | 
			
		||||
  perf->index_build = timer.ElapsedMicrosecondsAndReset();
 | 
			
		||||
  timer.stopTimer();
 | 
			
		||||
 | 
			
		||||
  std::unordered_map<std::string, int> inc_to_line;
 | 
			
		||||
  // TODO
 | 
			
		||||
 | 
			
		||||
@ -27,8 +27,6 @@ struct IndexFunc;
 | 
			
		||||
struct IndexVar;
 | 
			
		||||
struct QueryFile;
 | 
			
		||||
 | 
			
		||||
using RawId = uint32_t;
 | 
			
		||||
 | 
			
		||||
struct SymbolIdx {
 | 
			
		||||
  Usr usr;
 | 
			
		||||
  SymbolKind kind;
 | 
			
		||||
@ -153,19 +151,9 @@ struct TypeDef : NameMixin<TypeDef> {
 | 
			
		||||
  NtString hover;
 | 
			
		||||
  NtString comments;
 | 
			
		||||
 | 
			
		||||
  // While a class/type can technically have a separate declaration/definition,
 | 
			
		||||
  // it doesn't really happen in practice. The declaration never contains
 | 
			
		||||
  // comments or insightful information. The user always wants to jump from
 | 
			
		||||
  // the declaration to the definition - never the other way around like in
 | 
			
		||||
  // functions and (less often) variables.
 | 
			
		||||
  //
 | 
			
		||||
  // It's also difficult to identify a `class Foo;` statement with the clang
 | 
			
		||||
  // indexer API (it's doable using cursor AST traversal), so we don't bother
 | 
			
		||||
  // supporting the feature.
 | 
			
		||||
  Maybe<Use> spell;
 | 
			
		||||
  Maybe<Use> extent;
 | 
			
		||||
 | 
			
		||||
  // Immediate parent types.
 | 
			
		||||
  std::vector<Usr> bases;
 | 
			
		||||
 | 
			
		||||
  // Types, functions, and variables defined in this type.
 | 
			
		||||
@ -221,8 +209,6 @@ struct VarDef : NameMixin<VarDef> {
 | 
			
		||||
  std::string detailed_name;
 | 
			
		||||
  NtString hover;
 | 
			
		||||
  NtString comments;
 | 
			
		||||
  // TODO: definitions should be a list of ranges, since there can be more
 | 
			
		||||
  //       than one - when??
 | 
			
		||||
  Maybe<Use> spell;
 | 
			
		||||
  Maybe<Use> extent;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,87 +0,0 @@
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
 | 
			
		||||
#include <doctest/doctest.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
// VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent
 | 
			
		||||
// text documents.
 | 
			
		||||
// We use a UTF-8 iterator to approximate UTF-16 in the specification (weird).
 | 
			
		||||
// This is good enough and fails only for UTF-16 surrogate pairs.
 | 
			
		||||
int GetOffsetForPosition(lsPosition position, std::string_view content) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  for (; position.line > 0 && i < content.size(); i++)
 | 
			
		||||
    if (content[i] == '\n')
 | 
			
		||||
      position.line--;
 | 
			
		||||
  for (; position.character > 0 && i < content.size(); position.character--)
 | 
			
		||||
    if (uint8_t(content[i++]) >= 128) {
 | 
			
		||||
      // Skip 0b10xxxxxx
 | 
			
		||||
      while (i < content.size() && uint8_t(content[i]) >= 128 &&
 | 
			
		||||
             uint8_t(content[i]) < 192)
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
  return int(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
			
		||||
                                        std::string_view content) {
 | 
			
		||||
  int start = GetOffsetForPosition(position, content);
 | 
			
		||||
  int end = start + 1;
 | 
			
		||||
  char c;
 | 
			
		||||
 | 
			
		||||
  // We search for :: before the cursor but not after to get the qualifier.
 | 
			
		||||
  for (; start > 0; start--) {
 | 
			
		||||
    c = content[start - 1];
 | 
			
		||||
    if (isalnum(c) || c == '_')
 | 
			
		||||
      ;
 | 
			
		||||
    else if (c == ':' && start > 1 && content[start - 2] == ':')
 | 
			
		||||
      start--;
 | 
			
		||||
    else
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (; end < (int)content.size(); end++)
 | 
			
		||||
    if (c = content[end], !(isalnum(c) || c == '_'))
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
  return content.substr(start, end - start);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Find discontinous |search| in |content|.
 | 
			
		||||
// Return |found| and the count of skipped chars before found.
 | 
			
		||||
int ReverseSubseqMatch(std::string_view pat,
 | 
			
		||||
                       std::string_view text,
 | 
			
		||||
                       int case_sensitivity) {
 | 
			
		||||
  if (case_sensitivity == 1)
 | 
			
		||||
    case_sensitivity = std::any_of(pat.begin(), pat.end(), isupper) ? 2 : 0;
 | 
			
		||||
  int j = pat.size();
 | 
			
		||||
  if (!j)
 | 
			
		||||
    return text.size();
 | 
			
		||||
  for (int i = text.size(); i--;)
 | 
			
		||||
    if ((case_sensitivity ? text[i] == pat[j - 1]
 | 
			
		||||
                          : tolower(text[i]) == tolower(pat[j - 1])) &&
 | 
			
		||||
        !--j)
 | 
			
		||||
      return i;
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_SUITE("Offset") {
 | 
			
		||||
  TEST_CASE("past end") {
 | 
			
		||||
    std::string content = "foo";
 | 
			
		||||
    int offset = GetOffsetForPosition(lsPosition{10, 10}, content);
 | 
			
		||||
    REQUIRE(offset <= content.size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TEST_CASE("in middle of content") {
 | 
			
		||||
    std::string content = "abcdefghijk";
 | 
			
		||||
    for (int i = 0; i < content.size(); ++i) {
 | 
			
		||||
      int offset = GetOffsetForPosition(lsPosition{0, i}, content);
 | 
			
		||||
      REQUIRE(i == offset);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TEST_CASE("at end of content") {
 | 
			
		||||
    REQUIRE(GetOffsetForPosition(lsPosition{0, 0}, "") == 0);
 | 
			
		||||
    REQUIRE(GetOffsetForPosition(lsPosition{0, 1}, "a") == 1);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,16 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "lsp.h"
 | 
			
		||||
 | 
			
		||||
#include <string_view>
 | 
			
		||||
#include <tuple>
 | 
			
		||||
 | 
			
		||||
// Utility method to map |position| to an offset inside of |content|.
 | 
			
		||||
int GetOffsetForPosition(lsPosition position, std::string_view content);
 | 
			
		||||
 | 
			
		||||
std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
			
		||||
                                        std::string_view content);
 | 
			
		||||
 | 
			
		||||
int ReverseSubseqMatch(std::string_view pat,
 | 
			
		||||
                       std::string_view text,
 | 
			
		||||
                       int case_sensitivity);
 | 
			
		||||
@ -129,12 +129,10 @@ int main(int argc, char** argv) {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unordered_map<MethodType, Timer> request_times;
 | 
			
		||||
 | 
			
		||||
    // The thread that reads from stdin and dispatchs commands to the main thread.
 | 
			
		||||
    pipeline::LaunchStdin(&request_times);
 | 
			
		||||
    pipeline::LaunchStdin();
 | 
			
		||||
    // The thread that writes responses from the main thread to stdout.
 | 
			
		||||
    pipeline::LaunchStdout(&request_times);
 | 
			
		||||
    pipeline::LaunchStdout();
 | 
			
		||||
    // Main thread which also spawns indexer threads upon the "initialize" request.
 | 
			
		||||
    pipeline::MainLoop();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
#include "log.hh"
 | 
			
		||||
#include "project.h"
 | 
			
		||||
#include "query_utils.h"
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,6 @@
 | 
			
		||||
#include "working_files.h"
 | 
			
		||||
using namespace ccls;
 | 
			
		||||
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
 | 
			
		||||
#include <regex>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,3 @@
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "pipeline.hh"
 | 
			
		||||
#include "query_utils.h"
 | 
			
		||||
 | 
			
		||||
@ -1,72 +0,0 @@
 | 
			
		||||
#include "clang_format.h"
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "pipeline.hh"
 | 
			
		||||
using namespace ccls;
 | 
			
		||||
#include "working_files.h"
 | 
			
		||||
 | 
			
		||||
#include <loguru.hpp>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
MethodType kMethodType = "textDocument/rangeFormatting";
 | 
			
		||||
 | 
			
		||||
struct lsTextDocumentRangeFormattingParams {
 | 
			
		||||
  lsTextDocumentIdentifier textDocument;
 | 
			
		||||
  lsRange range;
 | 
			
		||||
  lsFormattingOptions options;
 | 
			
		||||
};
 | 
			
		||||
MAKE_REFLECT_STRUCT(lsTextDocumentRangeFormattingParams,
 | 
			
		||||
                    textDocument,
 | 
			
		||||
                    range,
 | 
			
		||||
                    options);
 | 
			
		||||
 | 
			
		||||
struct In_TextDocumentRangeFormatting : public RequestInMessage {
 | 
			
		||||
  MethodType GetMethodType() const override { return kMethodType; }
 | 
			
		||||
  lsTextDocumentRangeFormattingParams params;
 | 
			
		||||
};
 | 
			
		||||
MAKE_REFLECT_STRUCT(In_TextDocumentRangeFormatting, id, params);
 | 
			
		||||
REGISTER_IN_MESSAGE(In_TextDocumentRangeFormatting);
 | 
			
		||||
 | 
			
		||||
struct Out_TextDocumentRangeFormatting
 | 
			
		||||
    : public lsOutMessage<Out_TextDocumentRangeFormatting> {
 | 
			
		||||
  lsRequestId id;
 | 
			
		||||
  std::vector<lsTextEdit> result;
 | 
			
		||||
};
 | 
			
		||||
MAKE_REFLECT_STRUCT(Out_TextDocumentRangeFormatting, jsonrpc, id, result);
 | 
			
		||||
 | 
			
		||||
struct Handler_TextDocumentRangeFormatting
 | 
			
		||||
    : BaseMessageHandler<In_TextDocumentRangeFormatting> {
 | 
			
		||||
  MethodType GetMethodType() const override { return kMethodType; }
 | 
			
		||||
 | 
			
		||||
  void Run(In_TextDocumentRangeFormatting* request) override {
 | 
			
		||||
    Out_TextDocumentRangeFormatting response;
 | 
			
		||||
    response.id = request->id;
 | 
			
		||||
#if USE_CLANG_CXX
 | 
			
		||||
    QueryFile* file;
 | 
			
		||||
    if (!FindFileOrFail(db, project, request->id,
 | 
			
		||||
                        request->params.textDocument.uri.GetPath(), &file)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WorkingFile* working_file =
 | 
			
		||||
        working_files->GetFileByFilename(file->def->path);
 | 
			
		||||
 | 
			
		||||
    int start = GetOffsetForPosition(request->params.range.start,
 | 
			
		||||
                                     working_file->buffer_content),
 | 
			
		||||
        end = GetOffsetForPosition(request->params.range.end,
 | 
			
		||||
                                   working_file->buffer_content);
 | 
			
		||||
    response.result = ConvertClangReplacementsIntoTextEdits(
 | 
			
		||||
        working_file->buffer_content,
 | 
			
		||||
        ClangFormatDocument(working_file, start, end, request->params.options));
 | 
			
		||||
#else
 | 
			
		||||
    LOG_S(WARNING) << "You must compile ccls with --use-clang-cxx to use "
 | 
			
		||||
                      "textDocument/rangeFormatting.";
 | 
			
		||||
    // TODO: Fallback to execute the clang-format binary?
 | 
			
		||||
    response.result = {};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    pipeline::WriteStdout(kMethodType, response);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRangeFormatting);
 | 
			
		||||
}  // namespace
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
#include "fuzzy_match.h"
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
#include "message_handler.h"
 | 
			
		||||
#include "pipeline.hh"
 | 
			
		||||
#include "query_utils.h"
 | 
			
		||||
 | 
			
		||||
@ -11,10 +11,10 @@
 | 
			
		||||
#include "project.h"
 | 
			
		||||
#include "query_utils.h"
 | 
			
		||||
#include "pipeline.hh"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
#include <llvm/ADT/Twine.h>
 | 
			
		||||
#include <llvm/Support/Threading.h>
 | 
			
		||||
#include <llvm/Support/Timer.h>
 | 
			
		||||
using namespace llvm;
 | 
			
		||||
 | 
			
		||||
#include <thread>
 | 
			
		||||
@ -237,14 +237,15 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
 | 
			
		||||
 | 
			
		||||
    // Write current index to disk if requested.
 | 
			
		||||
    LOG_S(INFO) << "store index for " << path;
 | 
			
		||||
    Timer time;
 | 
			
		||||
    {
 | 
			
		||||
      Timer timer("write", "store index");
 | 
			
		||||
      timer.startTimer();
 | 
			
		||||
      std::string cache_path = GetCachePath(path);
 | 
			
		||||
      WriteToFile(cache_path, curr->file_contents);
 | 
			
		||||
      WriteToFile(AppendSerializationFormat(cache_path),
 | 
			
		||||
                  Serialize(g_config->cacheFormat, *curr));
 | 
			
		||||
      timer.stopTimer();
 | 
			
		||||
    }
 | 
			
		||||
    perf.index_save_to_disk = time.ElapsedMicrosecondsAndReset();
 | 
			
		||||
 | 
			
		||||
    vfs->Reset(path_to_index);
 | 
			
		||||
    if (entry.id >= 0) {
 | 
			
		||||
@ -255,7 +256,6 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
 | 
			
		||||
 | 
			
		||||
    // Build delta update.
 | 
			
		||||
    IndexUpdate update = IndexUpdate::CreateDelta(prev.get(), curr.get());
 | 
			
		||||
    perf.index_make_delta = time.ElapsedMicrosecondsAndReset();
 | 
			
		||||
    LOG_S(INFO) << "built index for " << path << " (is_delta=" << !!prev << ")";
 | 
			
		||||
 | 
			
		||||
    on_indexed->PushBack({std::move(update), perf}, request.is_interactive);
 | 
			
		||||
@ -264,15 +264,6 @@ bool Indexer_Parse(DiagnosticsEngine* diag_engine,
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function returns true if e2e timing should be displayed for the given
 | 
			
		||||
// MethodId.
 | 
			
		||||
bool ShouldDisplayMethodTiming(MethodType type) {
 | 
			
		||||
  return
 | 
			
		||||
    type != kMethodType_TextDocumentPublishDiagnostics &&
 | 
			
		||||
    type != kMethodType_CclsPublishInactiveRegions &&
 | 
			
		||||
    type != kMethodType_Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
void Init() {
 | 
			
		||||
@ -316,20 +307,22 @@ void Main_OnIndexed(DB* db,
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Timer time;
 | 
			
		||||
  Timer timer("apply", "apply index");
 | 
			
		||||
  timer.startTimer();
 | 
			
		||||
  db->ApplyIndexUpdate(&response->update);
 | 
			
		||||
  timer.stopTimer();
 | 
			
		||||
 | 
			
		||||
  // Update indexed content, inactive lines, and semantic highlighting.
 | 
			
		||||
  if (response->update.files_def_update) {
 | 
			
		||||
    auto& update = *response->update.files_def_update;
 | 
			
		||||
    time.ResetAndPrint("apply index for " + update.value.path);
 | 
			
		||||
    LOG_S(INFO) << "apply index for " << update.first.path;
 | 
			
		||||
    if (WorkingFile* working_file =
 | 
			
		||||
            working_files->GetFileByFilename(update.value.path)) {
 | 
			
		||||
            working_files->GetFileByFilename(update.first.path)) {
 | 
			
		||||
      // Update indexed content.
 | 
			
		||||
      working_file->SetIndexContent(update.file_content);
 | 
			
		||||
      working_file->SetIndexContent(update.second);
 | 
			
		||||
 | 
			
		||||
      // Inactive lines.
 | 
			
		||||
      EmitInactiveLines(working_file, update.value.inactive_regions);
 | 
			
		||||
      EmitInactiveLines(working_file, update.first.inactive_regions);
 | 
			
		||||
 | 
			
		||||
      // Semantic highlighting.
 | 
			
		||||
      int file_id =
 | 
			
		||||
@ -340,8 +333,8 @@ void Main_OnIndexed(DB* db,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LaunchStdin(std::unordered_map<MethodType, Timer>* request_times) {
 | 
			
		||||
  std::thread([request_times]() {
 | 
			
		||||
void LaunchStdin() {
 | 
			
		||||
  std::thread([]() {
 | 
			
		||||
    set_thread_name("stdin");
 | 
			
		||||
    while (true) {
 | 
			
		||||
      std::unique_ptr<InMessage> message;
 | 
			
		||||
@ -367,7 +360,6 @@ void LaunchStdin(std::unordered_map<MethodType, Timer>* request_times) {
 | 
			
		||||
 | 
			
		||||
      // Cache |method_id| so we can access it after moving |message|.
 | 
			
		||||
      MethodType method_type = message->GetMethodType();
 | 
			
		||||
      (*request_times)[method_type] = Timer();
 | 
			
		||||
 | 
			
		||||
      on_request->PushBack(std::move(message));
 | 
			
		||||
 | 
			
		||||
@ -379,7 +371,7 @@ void LaunchStdin(std::unordered_map<MethodType, Timer>* request_times) {
 | 
			
		||||
  }).detach();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LaunchStdout(std::unordered_map<MethodType, Timer>* request_times) {
 | 
			
		||||
void LaunchStdout() {
 | 
			
		||||
  std::thread([=]() {
 | 
			
		||||
    set_thread_name("stdout");
 | 
			
		||||
 | 
			
		||||
@ -391,11 +383,6 @@ void LaunchStdout(std::unordered_map<MethodType, Timer>* request_times) {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (auto& message : messages) {
 | 
			
		||||
        if (ShouldDisplayMethodTiming(message.method)) {
 | 
			
		||||
          Timer time = (*request_times)[message.method];
 | 
			
		||||
          time.ResetAndPrint("[e2e] Running " + std::string(message.method));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fwrite(message.content.c_str(), message.content.size(), 1, stdout);
 | 
			
		||||
        fflush(stdout);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@
 | 
			
		||||
 | 
			
		||||
#include "method.h"
 | 
			
		||||
#include "query.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
@ -17,8 +16,8 @@ struct lsBaseOutMessage;
 | 
			
		||||
namespace ccls::pipeline {
 | 
			
		||||
 | 
			
		||||
void Init();
 | 
			
		||||
void LaunchStdin(std::unordered_map<MethodType, Timer>* request_times);
 | 
			
		||||
void LaunchStdout(std::unordered_map<MethodType, Timer>* request_times);
 | 
			
		||||
void LaunchStdin();
 | 
			
		||||
void LaunchStdout();
 | 
			
		||||
void Indexer_Main(DiagnosticsEngine* diag_engine,
 | 
			
		||||
                  VFS* vfs,
 | 
			
		||||
                  Project* project,
 | 
			
		||||
 | 
			
		||||
@ -148,7 +148,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
 | 
			
		||||
              return a.range.start < b.range.start;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
  return QueryFile::DefUpdate(def, indexed.file_contents);
 | 
			
		||||
  return {std::move(def), std::move(indexed.file_contents)};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true if an element with the same file is found.
 | 
			
		||||
@ -342,11 +342,11 @@ void DB::ApplyIndexUpdate(IndexUpdate* u) {
 | 
			
		||||
 | 
			
		||||
int DB::Update(QueryFile::DefUpdate&& u) {
 | 
			
		||||
  int id = files.size();
 | 
			
		||||
  auto it = name2file_id.try_emplace(LowerPathIfInsensitive(u.value.path), id);
 | 
			
		||||
  auto it = name2file_id.try_emplace(LowerPathIfInsensitive(u.first.path), id);
 | 
			
		||||
  if (it.second)
 | 
			
		||||
    files.emplace_back().id = id;
 | 
			
		||||
  QueryFile& existing = files[it.first->second];
 | 
			
		||||
  existing.def = u.value;
 | 
			
		||||
  existing.def = u.first;
 | 
			
		||||
  return existing.id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								src/query.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/query.h
									
									
									
									
									
								
							@ -6,21 +6,6 @@
 | 
			
		||||
#include <llvm/ADT/DenseMap.h>
 | 
			
		||||
#include <llvm/ADT/SmallVector.h>
 | 
			
		||||
 | 
			
		||||
struct QueryFile;
 | 
			
		||||
struct QueryType;
 | 
			
		||||
struct QueryFunc;
 | 
			
		||||
struct QueryVar;
 | 
			
		||||
struct DB;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct WithFileContent {
 | 
			
		||||
  T value;
 | 
			
		||||
  std::string file_content;
 | 
			
		||||
 | 
			
		||||
  WithFileContent(const T& value, const std::string& file_content)
 | 
			
		||||
      : value(value), file_content(file_content) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct QueryFile {
 | 
			
		||||
  struct Def {
 | 
			
		||||
    std::string path;
 | 
			
		||||
@ -38,7 +23,7 @@ struct QueryFile {
 | 
			
		||||
    std::vector<std::string> dependencies;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  using DefUpdate = WithFileContent<Def>;
 | 
			
		||||
  using DefUpdate = std::pair<Def, std::string>;
 | 
			
		||||
 | 
			
		||||
  int id = -1;
 | 
			
		||||
  std::optional<Def> def;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								src/utils.cc
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/utils.cc
									
									
									
									
									
								
							@ -134,6 +134,24 @@ std::optional<int64_t> LastWriteTime(const std::string& filename) {
 | 
			
		||||
  return Status.getLastModificationTime().time_since_epoch().count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Find discontinous |search| in |content|.
 | 
			
		||||
// Return |found| and the count of skipped chars before found.
 | 
			
		||||
int ReverseSubseqMatch(std::string_view pat,
 | 
			
		||||
                       std::string_view text,
 | 
			
		||||
                       int case_sensitivity) {
 | 
			
		||||
  if (case_sensitivity == 1)
 | 
			
		||||
    case_sensitivity = std::any_of(pat.begin(), pat.end(), isupper) ? 2 : 0;
 | 
			
		||||
  int j = pat.size();
 | 
			
		||||
  if (!j)
 | 
			
		||||
    return text.size();
 | 
			
		||||
  for (int i = text.size(); i--;)
 | 
			
		||||
    if ((case_sensitivity ? text[i] == pat[j - 1]
 | 
			
		||||
                          : tolower(text[i]) == tolower(pat[j - 1])) &&
 | 
			
		||||
        !--j)
 | 
			
		||||
      return i;
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string GetDefaultResourceDirectory() {
 | 
			
		||||
  return DEFAULT_RESOURCE_DIRECTORY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -58,6 +58,10 @@ std::optional<std::string> ReadContent(const std::string& filename);
 | 
			
		||||
void WriteToFile(const std::string& filename, const std::string& content);
 | 
			
		||||
std::optional<int64_t> LastWriteTime(const std::string& filename);
 | 
			
		||||
 | 
			
		||||
int ReverseSubseqMatch(std::string_view pat,
 | 
			
		||||
                       std::string_view text,
 | 
			
		||||
                       int case_sensitivity);
 | 
			
		||||
 | 
			
		||||
// http://stackoverflow.com/a/38140932
 | 
			
		||||
//
 | 
			
		||||
//  struct SomeHashKey {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
#include "working_files.h"
 | 
			
		||||
 | 
			
		||||
#include "lex_utils.h"
 | 
			
		||||
#include "log.hh"
 | 
			
		||||
#include "position.h"
 | 
			
		||||
 | 
			
		||||
@ -545,3 +544,46 @@ WorkingFiles::Snapshot WorkingFiles::AsSnapshot(
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VSCode (UTF-16) disagrees with Emacs lsp-mode (UTF-8) on how to represent
 | 
			
		||||
// text documents.
 | 
			
		||||
// We use a UTF-8 iterator to approximate UTF-16 in the specification (weird).
 | 
			
		||||
// This is good enough and fails only for UTF-16 surrogate pairs.
 | 
			
		||||
int GetOffsetForPosition(lsPosition position, std::string_view content) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  for (; position.line > 0 && i < content.size(); i++)
 | 
			
		||||
    if (content[i] == '\n')
 | 
			
		||||
      position.line--;
 | 
			
		||||
  for (; position.character > 0 && i < content.size(); position.character--)
 | 
			
		||||
    if (uint8_t(content[i++]) >= 128) {
 | 
			
		||||
      // Skip 0b10xxxxxx
 | 
			
		||||
      while (i < content.size() && uint8_t(content[i]) >= 128 &&
 | 
			
		||||
             uint8_t(content[i]) < 192)
 | 
			
		||||
        i++;
 | 
			
		||||
    }
 | 
			
		||||
  return int(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
			
		||||
                                        std::string_view content) {
 | 
			
		||||
  int start = GetOffsetForPosition(position, content);
 | 
			
		||||
  int end = start + 1;
 | 
			
		||||
  char c;
 | 
			
		||||
 | 
			
		||||
  // We search for :: before the cursor but not after to get the qualifier.
 | 
			
		||||
  for (; start > 0; start--) {
 | 
			
		||||
    c = content[start - 1];
 | 
			
		||||
    if (isalnum(c) || c == '_')
 | 
			
		||||
      ;
 | 
			
		||||
    else if (c == ':' && start > 1 && content[start - 2] == ':')
 | 
			
		||||
      start--;
 | 
			
		||||
    else
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (; end < (int)content.size(); end++)
 | 
			
		||||
    if (c = content[end], !(isalnum(c) || c == '_'))
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
  return content.substr(start, end - start);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -117,3 +117,8 @@ struct WorkingFiles {
 | 
			
		||||
  std::vector<std::unique_ptr<WorkingFile>> files;
 | 
			
		||||
  std::mutex files_mutex;  // Protects |files|.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int GetOffsetForPosition(lsPosition position, std::string_view content);
 | 
			
		||||
 | 
			
		||||
std::string_view LexIdentifierAroundPos(lsPosition position,
 | 
			
		||||
                                        std::string_view content);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user