mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 04:32:33 +00:00 
			
		
		
		
	Use indented TEST_SUITE
This commit is contained in:
		
							parent
							
								
									424c7b69db
								
							
						
					
					
						commit
						297ed1d13e
					
				| @ -3257,193 +3257,187 @@ int main(int argc, char** argv) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("LexFunctionDeclaration"); | ||||
| TEST_SUITE("LexFunctionDeclaration") { | ||||
|   TEST_CASE("simple") { | ||||
|     std::string buffer_content = " void Foo(); "; | ||||
|     lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|     std::string insert_text; | ||||
|     int newlines_after_name = 0; | ||||
| 
 | ||||
| TEST_CASE("simple") { | ||||
|   std::string buffer_content = " void Foo(); "; | ||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|   std::string insert_text; | ||||
|   int newlines_after_name = 0; | ||||
|     LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                           &newlines_after_name); | ||||
|     REQUIRE(insert_text == "void Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                          &newlines_after_name); | ||||
|   REQUIRE(insert_text == "void Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
|     LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                           &insert_text, &newlines_after_name); | ||||
|     REQUIRE(insert_text == "void Type::Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
|   } | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                          &insert_text, &newlines_after_name); | ||||
|   REQUIRE(insert_text == "void Type::Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
|   TEST_CASE("ctor") { | ||||
|     std::string buffer_content = " Foo(); "; | ||||
|     lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|     std::string insert_text; | ||||
|     int newlines_after_name = 0; | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), | ||||
|                           &insert_text, &newlines_after_name); | ||||
|     REQUIRE(insert_text == "Foo::Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("dtor") { | ||||
|     std::string buffer_content = " ~Foo(); "; | ||||
|     lsPosition declaration = CharPos(buffer_content, '~'); | ||||
|     std::string insert_text; | ||||
|     int newlines_after_name = 0; | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), | ||||
|                           &insert_text, &newlines_after_name); | ||||
|     REQUIRE(insert_text == "Foo::~Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("complex return type") { | ||||
|     std::string buffer_content = " std::vector<int> Foo(); "; | ||||
|     lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|     std::string insert_text; | ||||
|     int newlines_after_name = 0; | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                           &newlines_after_name); | ||||
|     REQUIRE(insert_text == "std::vector<int> Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                           &insert_text, &newlines_after_name); | ||||
|     REQUIRE(insert_text == "std::vector<int> Type::Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("extra complex return type") { | ||||
|     std::string buffer_content = " std::function < int() > \n Foo(); "; | ||||
|     lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|     std::string insert_text; | ||||
|     int newlines_after_name = 0; | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                           &newlines_after_name); | ||||
|     REQUIRE(insert_text == "std::function < int() > \n Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                           &insert_text, &newlines_after_name); | ||||
|     REQUIRE(insert_text == "std::function < int() > \n Type::Foo() {\n}"); | ||||
|     REQUIRE(newlines_after_name == 0); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("parameters") { | ||||
|     std::string buffer_content = "void Foo(int a,\n\n    int b); "; | ||||
|     lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|     std::string insert_text; | ||||
|     int newlines_after_name = 0; | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                           &newlines_after_name); | ||||
|     REQUIRE(insert_text == "void Foo(int a,\n\n    int b) {\n}"); | ||||
|     REQUIRE(newlines_after_name == 2); | ||||
| 
 | ||||
|     LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                           &insert_text, &newlines_after_name); | ||||
|     REQUIRE(insert_text == "void Type::Foo(int a,\n\n    int b) {\n}"); | ||||
|     REQUIRE(newlines_after_name == 2); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("ctor") { | ||||
|   std::string buffer_content = " Foo(); "; | ||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|   std::string insert_text; | ||||
|   int newlines_after_name = 0; | ||||
| TEST_SUITE("LexWordAroundPos") { | ||||
|   TEST_CASE("edges") { | ||||
|     std::string content = "Foobar"; | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'F'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'o'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'b'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'a'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'r'), content) == "Foobar"); | ||||
|   } | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), | ||||
|                          &insert_text, &newlines_after_name); | ||||
|   REQUIRE(insert_text == "Foo::Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
|   TEST_CASE("simple") { | ||||
|     std::string content = "  Foobar  "; | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'F'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'o'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'b'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'a'), content) == "Foobar"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'r'), content) == "Foobar"); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("underscores and numbers") { | ||||
|     std::string content = "  _my_t5ype7  "; | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, '_'), content) == "_my_t5ype7"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, '5'), content) == "_my_t5ype7"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, 'e'), content) == "_my_t5ype7"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, '7'), content) == "_my_t5ype7"); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("dot, dash, colon are skipped") { | ||||
|     std::string content = "1. 2- 3:"; | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, '1'), content) == "1"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, '2'), content) == "2"); | ||||
|     REQUIRE(LexWordAroundPos(CharPos(content, '3'), content) == "3"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("dtor") { | ||||
|   std::string buffer_content = " ~Foo(); "; | ||||
|   lsPosition declaration = CharPos(buffer_content, '~'); | ||||
|   std::string insert_text; | ||||
|   int newlines_after_name = 0; | ||||
| TEST_SUITE("FindIncludeLine") { | ||||
|   TEST_CASE("in document") { | ||||
|     std::vector<std::string> lines = { | ||||
|         "#include <bbb>",  // 0
 | ||||
|         "#include <ddd>"   // 1
 | ||||
|     }; | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), | ||||
|                          &insert_text, &newlines_after_name); | ||||
|   REQUIRE(insert_text == "Foo::~Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <bbb>") == nullopt); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("insert before") { | ||||
|     std::vector<std::string> lines = { | ||||
|         "#include <bbb>",  // 0
 | ||||
|         "#include <ddd>"   // 1
 | ||||
|     }; | ||||
| 
 | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <aaa>") == 0); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("insert middle") { | ||||
|     std::vector<std::string> lines = { | ||||
|         "#include <bbb>",  // 0
 | ||||
|         "#include <ddd>"   // 1
 | ||||
|     }; | ||||
| 
 | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <ccc>") == 1); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("insert after") { | ||||
|     std::vector<std::string> lines = { | ||||
|         "#include <bbb>",  // 0
 | ||||
|         "#include <ddd>",  // 1
 | ||||
|         "",                // 2
 | ||||
|     }; | ||||
| 
 | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <eee>") == 2); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("ignore header") { | ||||
|     std::vector<std::string> lines = { | ||||
|         "// FOOBAR",       // 0
 | ||||
|         "// FOOBAR",       // 1
 | ||||
|         "// FOOBAR",       // 2
 | ||||
|         "// FOOBAR",       // 3
 | ||||
|         "",                // 4
 | ||||
|         "#include <bbb>",  // 5
 | ||||
|         "#include <ddd>",  // 6
 | ||||
|         "",                // 7
 | ||||
|     }; | ||||
| 
 | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <a>") == 5); | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <c>") == 6); | ||||
|     REQUIRE(FindIncludeLine(lines, "#include <e>") == 7); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("complex return type") { | ||||
|   std::string buffer_content = " std::vector<int> Foo(); "; | ||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|   std::string insert_text; | ||||
|   int newlines_after_name = 0; | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                          &newlines_after_name); | ||||
|   REQUIRE(insert_text == "std::vector<int> Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                          &insert_text, &newlines_after_name); | ||||
|   REQUIRE(insert_text == "std::vector<int> Type::Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("extra complex return type") { | ||||
|   std::string buffer_content = " std::function < int() > \n Foo(); "; | ||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|   std::string insert_text; | ||||
|   int newlines_after_name = 0; | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                          &newlines_after_name); | ||||
|   REQUIRE(insert_text == "std::function < int() > \n Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                          &insert_text, &newlines_after_name); | ||||
|   REQUIRE(insert_text == "std::function < int() > \n Type::Foo() {\n}"); | ||||
|   REQUIRE(newlines_after_name == 0); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("parameters") { | ||||
|   std::string buffer_content = "void Foo(int a,\n\n    int b); "; | ||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); | ||||
|   std::string insert_text; | ||||
|   int newlines_after_name = 0; | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||
|                          &newlines_after_name); | ||||
|   REQUIRE(insert_text == "void Foo(int a,\n\n    int b) {\n}"); | ||||
|   REQUIRE(newlines_after_name == 2); | ||||
| 
 | ||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||
|                          &insert_text, &newlines_after_name); | ||||
|   REQUIRE(insert_text == "void Type::Foo(int a,\n\n    int b) {\n}"); | ||||
|   REQUIRE(newlines_after_name == 2); | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
| 
 | ||||
| TEST_SUITE("LexWordAroundPos"); | ||||
| 
 | ||||
| TEST_CASE("edges") { | ||||
|   std::string content = "Foobar"; | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'F'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'o'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'b'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'a'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'r'), content) == "Foobar"); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("simple") { | ||||
|   std::string content = "  Foobar  "; | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'F'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'o'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'b'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'a'), content) == "Foobar"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'r'), content) == "Foobar"); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("underscores and numbers") { | ||||
|   std::string content = "  _my_t5ype7  "; | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, '_'), content) == "_my_t5ype7"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, '5'), content) == "_my_t5ype7"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, 'e'), content) == "_my_t5ype7"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, '7'), content) == "_my_t5ype7"); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("dot, dash, colon are skipped") { | ||||
|   std::string content = "1. 2- 3:"; | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, '1'), content) == "1"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, '2'), content) == "2"); | ||||
|   REQUIRE(LexWordAroundPos(CharPos(content, '3'), content) == "3"); | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
| 
 | ||||
| TEST_SUITE("FindIncludeLine"); | ||||
| 
 | ||||
| TEST_CASE("in document") { | ||||
|   std::vector<std::string> lines = { | ||||
|       "#include <bbb>",  // 0
 | ||||
|       "#include <ddd>"   // 1
 | ||||
|   }; | ||||
| 
 | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <bbb>") == nullopt); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("insert before") { | ||||
|   std::vector<std::string> lines = { | ||||
|       "#include <bbb>",  // 0
 | ||||
|       "#include <ddd>"   // 1
 | ||||
|   }; | ||||
| 
 | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <aaa>") == 0); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("insert middle") { | ||||
|   std::vector<std::string> lines = { | ||||
|       "#include <bbb>",  // 0
 | ||||
|       "#include <ddd>"   // 1
 | ||||
|   }; | ||||
| 
 | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <ccc>") == 1); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("insert after") { | ||||
|   std::vector<std::string> lines = { | ||||
|       "#include <bbb>",  // 0
 | ||||
|       "#include <ddd>",  // 1
 | ||||
|       "",                // 2
 | ||||
|   }; | ||||
| 
 | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <eee>") == 2); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("ignore header") { | ||||
|   std::vector<std::string> lines = { | ||||
|       "// FOOBAR",       // 0
 | ||||
|       "// FOOBAR",       // 1
 | ||||
|       "// FOOBAR",       // 2
 | ||||
|       "// FOOBAR",       // 3
 | ||||
|       "",                // 4
 | ||||
|       "#include <bbb>",  // 5
 | ||||
|       "#include <ddd>",  // 6
 | ||||
|       "",                // 7
 | ||||
|   }; | ||||
| 
 | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <a>") == 5); | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <c>") == 6); | ||||
|   REQUIRE(FindIncludeLine(lines, "#include <e>") == 7); | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
|  | ||||
| @ -82,8 +82,6 @@ optional<std::string> ReadJsonRpcContentFrom( | ||||
|   return content; | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("FindIncludeLine"); | ||||
| 
 | ||||
| std::function<optional<char>()> MakeContentReader(std::string* content, | ||||
|                                                   bool can_be_empty) { | ||||
|   return [content, can_be_empty]() -> optional<char> { | ||||
| @ -97,31 +95,31 @@ std::function<optional<char>()> MakeContentReader(std::string* content, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("ReadContentFromSource") { | ||||
|   auto parse_correct = [](std::string content) -> std::string { | ||||
|     auto reader = MakeContentReader(&content, false /*can_be_empty*/); | ||||
|     auto got = ReadJsonRpcContentFrom(reader); | ||||
|     REQUIRE(got); | ||||
|     return got.value(); | ||||
|   }; | ||||
| TEST_SUITE("FindIncludeLine") { | ||||
|   TEST_CASE("ReadContentFromSource") { | ||||
|     auto parse_correct = [](std::string content) -> std::string { | ||||
|       auto reader = MakeContentReader(&content, false /*can_be_empty*/); | ||||
|       auto got = ReadJsonRpcContentFrom(reader); | ||||
|       REQUIRE(got); | ||||
|       return got.value(); | ||||
|     }; | ||||
| 
 | ||||
|   auto parse_incorrect = [](std::string content) -> optional<std::string> { | ||||
|     auto reader = MakeContentReader(&content, true /*can_be_empty*/); | ||||
|     return ReadJsonRpcContentFrom(reader); | ||||
|   }; | ||||
|     auto parse_incorrect = [](std::string content) -> optional<std::string> { | ||||
|       auto reader = MakeContentReader(&content, true /*can_be_empty*/); | ||||
|       return ReadJsonRpcContentFrom(reader); | ||||
|     }; | ||||
| 
 | ||||
|   REQUIRE(parse_correct("Content-Length: 0\r\n\r\n") == ""); | ||||
|   REQUIRE(parse_correct("Content-Length: 1\r\n\r\na") == "a"); | ||||
|   REQUIRE(parse_correct("Content-Length: 4\r\n\r\nabcd") == "abcd"); | ||||
|     REQUIRE(parse_correct("Content-Length: 0\r\n\r\n") == ""); | ||||
|     REQUIRE(parse_correct("Content-Length: 1\r\n\r\na") == "a"); | ||||
|     REQUIRE(parse_correct("Content-Length: 4\r\n\r\nabcd") == "abcd"); | ||||
| 
 | ||||
|   REQUIRE(parse_incorrect("ggg") == optional<std::string>()); | ||||
|   REQUIRE(parse_incorrect("Content-Length: 0\r\n") == optional<std::string>()); | ||||
|   REQUIRE(parse_incorrect("Content-Length: 5\r\n\r\nab") == | ||||
|           optional<std::string>()); | ||||
|     REQUIRE(parse_incorrect("ggg") == optional<std::string>()); | ||||
|     REQUIRE(parse_incorrect("Content-Length: 0\r\n") == optional<std::string>()); | ||||
|     REQUIRE(parse_incorrect("Content-Length: 5\r\n\r\nab") == | ||||
|             optional<std::string>()); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
| 
 | ||||
| optional<char> ReadCharFromStdinBlocking() { | ||||
|   // Bad stdin means parent process has probably exited. Either way, cquery
 | ||||
|   // can no longer be communicated with so just exit.
 | ||||
|  | ||||
| @ -213,59 +213,55 @@ bool SubstringMatch(const std::string& search, const std::string& content) { | ||||
|   return false; | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("Offset"); | ||||
| TEST_SUITE("Offset") { | ||||
|   TEST_CASE("past end") { | ||||
|     std::string content = "foo"; | ||||
|     int offset = GetOffsetForPosition(lsPosition(10, 10), content); | ||||
|     REQUIRE(offset <= content.size()); | ||||
|   } | ||||
| 
 | ||||
| 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("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); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("at end of content") { | ||||
|   REQUIRE(GetOffsetForPosition(lsPosition(0, 0), "") == 0); | ||||
|   REQUIRE(GetOffsetForPosition(lsPosition(0, 1), "a") == 1); | ||||
| TEST_SUITE("Substring") { | ||||
|   TEST_CASE("match") { | ||||
|     // Sanity.
 | ||||
|     REQUIRE(SubstringMatch("a", "aa")); | ||||
|     REQUIRE(SubstringMatch("aa", "aa")); | ||||
| 
 | ||||
|     // Empty string matches anything.
 | ||||
|     REQUIRE(SubstringMatch("", "")); | ||||
|     REQUIRE(SubstringMatch("", "aa")); | ||||
| 
 | ||||
|     // Match in start/middle/end.
 | ||||
|     REQUIRE(SubstringMatch("a", "abbbb")); | ||||
|     REQUIRE(SubstringMatch("a", "bbabb")); | ||||
|     REQUIRE(SubstringMatch("a", "bbbba")); | ||||
|     REQUIRE(SubstringMatch("aa", "aabbb")); | ||||
|     REQUIRE(SubstringMatch("aa", "bbaab")); | ||||
|     REQUIRE(SubstringMatch("aa", "bbbaa")); | ||||
| 
 | ||||
|     // Capitalization.
 | ||||
|     REQUIRE(SubstringMatch("aa", "aA")); | ||||
|     REQUIRE(SubstringMatch("aa", "Aa")); | ||||
|     REQUIRE(SubstringMatch("aa", "AA")); | ||||
| 
 | ||||
|     // Token skipping.
 | ||||
|     REQUIRE(SubstringMatch("ad", "abcd")); | ||||
|     REQUIRE(SubstringMatch("ad", "ABCD")); | ||||
| 
 | ||||
|     // Ordering.
 | ||||
|     REQUIRE(!SubstringMatch("ad", "dcba")); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
| 
 | ||||
| TEST_SUITE("Substring"); | ||||
| 
 | ||||
| TEST_CASE("match") { | ||||
|   // Sanity.
 | ||||
|   REQUIRE(SubstringMatch("a", "aa")); | ||||
|   REQUIRE(SubstringMatch("aa", "aa")); | ||||
| 
 | ||||
|   // Empty string matches anything.
 | ||||
|   REQUIRE(SubstringMatch("", "")); | ||||
|   REQUIRE(SubstringMatch("", "aa")); | ||||
| 
 | ||||
|   // Match in start/middle/end.
 | ||||
|   REQUIRE(SubstringMatch("a", "abbbb")); | ||||
|   REQUIRE(SubstringMatch("a", "bbabb")); | ||||
|   REQUIRE(SubstringMatch("a", "bbbba")); | ||||
|   REQUIRE(SubstringMatch("aa", "aabbb")); | ||||
|   REQUIRE(SubstringMatch("aa", "bbaab")); | ||||
|   REQUIRE(SubstringMatch("aa", "bbbaa")); | ||||
| 
 | ||||
|   // Capitalization.
 | ||||
|   REQUIRE(SubstringMatch("aa", "aA")); | ||||
|   REQUIRE(SubstringMatch("aa", "Aa")); | ||||
|   REQUIRE(SubstringMatch("aa", "AA")); | ||||
| 
 | ||||
|   // Token skipping.
 | ||||
|   REQUIRE(SubstringMatch("ad", "abcd")); | ||||
|   REQUIRE(SubstringMatch("ad", "ABCD")); | ||||
| 
 | ||||
|   // Ordering.
 | ||||
|   REQUIRE(!SubstringMatch("ad", "dcba")); | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
							
								
								
									
										22
									
								
								src/match.cc
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/match.cc
									
									
									
									
									
								
							| @ -76,16 +76,14 @@ bool GroupMatch::IsMatch(const std::string& value, | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("Matcher"); | ||||
| 
 | ||||
| TEST_CASE("sanity") { | ||||
|   // Matcher m("abc");
 | ||||
|   // TODO: check case
 | ||||
|   // CHECK(m.IsMatch("abc"));
 | ||||
|   // CHECK(m.IsMatch("fooabc"));
 | ||||
|   // CHECK(m.IsMatch("abc"));
 | ||||
|   // CHECK(m.IsMatch("abcfoo"));
 | ||||
|   // CHECK(m.IsMatch("11a11b11c11"));
 | ||||
| TEST_SUITE("Matcher") { | ||||
|   TEST_CASE("sanity") { | ||||
|     // Matcher m("abc");
 | ||||
|     // TODO: check case
 | ||||
|     // CHECK(m.IsMatch("abc"));
 | ||||
|     // CHECK(m.IsMatch("fooabc"));
 | ||||
|     // CHECK(m.IsMatch("abc"));
 | ||||
|     // CHECK(m.IsMatch("abcfoo"));
 | ||||
|     // CHECK(m.IsMatch("11a11b11c11"));
 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
|  | ||||
| @ -87,40 +87,38 @@ void MakeDirectoryRecursive(std::string path) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("Platform"); | ||||
| TEST_SUITE("Platform") { | ||||
|   TEST_CASE("Split strings") { | ||||
|     std::vector<std::string> actual = Split("/a/b/c/", '/'); | ||||
|     std::vector<std::string> expected{"a", "b", "c"}; | ||||
|     REQUIRE(actual == expected); | ||||
|   } | ||||
| 
 | ||||
| TEST_CASE("Split strings") { | ||||
|   std::vector<std::string> actual = Split("/a/b/c/", '/'); | ||||
|   std::vector<std::string> expected{"a", "b", "c"}; | ||||
|   REQUIRE(actual == expected); | ||||
| } | ||||
|   TEST_CASE("Mutex lock/unlock (single process)") { | ||||
|     auto m1 = CreatePlatformMutex("indexer-platformmutexttest"); | ||||
|     auto l1 = CreatePlatformScopedMutexLock(m1.get()); | ||||
|     auto m2 = CreatePlatformMutex("indexer-platformmutexttest"); | ||||
| 
 | ||||
| TEST_CASE("Mutex lock/unlock (single process)") { | ||||
|   auto m1 = CreatePlatformMutex("indexer-platformmutexttest"); | ||||
|   auto l1 = CreatePlatformScopedMutexLock(m1.get()); | ||||
|   auto m2 = CreatePlatformMutex("indexer-platformmutexttest"); | ||||
|     int value = 0; | ||||
| 
 | ||||
|   int value = 0; | ||||
| 
 | ||||
|   volatile bool did_run = false; | ||||
|   std::thread t([&]() { | ||||
|     did_run = true; | ||||
|     auto l2 = CreatePlatformScopedMutexLock(m2.get()); | ||||
|     value = 1; | ||||
|   }); | ||||
|   while (!did_run) | ||||
|     volatile bool did_run = false; | ||||
|     std::thread t([&]() { | ||||
|       did_run = true; | ||||
|       auto l2 = CreatePlatformScopedMutexLock(m2.get()); | ||||
|       value = 1; | ||||
|     }); | ||||
|     while (!did_run) | ||||
|       std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||||
|     std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||||
|   std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||||
| 
 | ||||
|   // Other thread has had a chance to run, but it should not have
 | ||||
|   // written to value yet (ie, it should be waiting).
 | ||||
|   REQUIRE(value == 0); | ||||
|     // Other thread has had a chance to run, but it should not have
 | ||||
|     // written to value yet (ie, it should be waiting).
 | ||||
|     REQUIRE(value == 0); | ||||
| 
 | ||||
|   // Release the lock, wait for other thread to finish. Verify it
 | ||||
|   // wrote the expected value.
 | ||||
|   l1.reset(); | ||||
|   t.join(); | ||||
|   REQUIRE(value == 1); | ||||
|     // Release the lock, wait for other thread to finish. Verify it
 | ||||
|     // wrote the expected value.
 | ||||
|     l1.reset(); | ||||
|     t.join(); | ||||
|     REQUIRE(value == 1); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
|  | ||||
							
								
								
									
										1682
									
								
								src/project.cc
									
									
									
									
									
								
							
							
						
						
									
										1682
									
								
								src/project.cc
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										252
									
								
								src/query.cc
									
									
									
									
									
								
							
							
						
						
									
										252
									
								
								src/query.cc
									
									
									
									
									
								
							| @ -823,132 +823,130 @@ void QueryDatabase::UpdateDetailedNames(size_t* qualified_name_index, | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("query"); | ||||
| TEST_SUITE("query") { | ||||
|   IndexUpdate GetDelta(IndexFile previous, IndexFile current) { | ||||
|     QueryDatabase db; | ||||
|     IdMap previous_map(&db, previous.id_cache); | ||||
|     IdMap current_map(&db, current.id_cache); | ||||
|     return IndexUpdate::CreateDelta(&previous_map, ¤t_map, &previous, | ||||
|                                     ¤t); | ||||
|   } | ||||
| 
 | ||||
| IndexUpdate GetDelta(IndexFile previous, IndexFile current) { | ||||
|   QueryDatabase db; | ||||
|   IdMap previous_map(&db, previous.id_cache); | ||||
|   IdMap current_map(&db, current.id_cache); | ||||
|   return IndexUpdate::CreateDelta(&previous_map, ¤t_map, &previous, | ||||
|                                   ¤t); | ||||
|   TEST_CASE("remove defs") { | ||||
|     IndexFile previous("foo.cc"); | ||||
|     IndexFile current("foo.cc"); | ||||
| 
 | ||||
|     previous.Resolve(previous.ToTypeId("usr1"))->def.definition_spelling = | ||||
|         Range(Position(1, 0)); | ||||
|     previous.Resolve(previous.ToFuncId("usr2"))->def.definition_spelling = | ||||
|         Range(Position(2, 0)); | ||||
|     previous.Resolve(previous.ToVarId("usr3"))->def.definition_spelling = | ||||
|         Range(Position(3, 0)); | ||||
| 
 | ||||
|     IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|     REQUIRE(update.types_removed == std::vector<Usr>{"usr1"}); | ||||
|     REQUIRE(update.funcs_removed == std::vector<Usr>{"usr2"}); | ||||
|     REQUIRE(update.vars_removed == std::vector<Usr>{"usr3"}); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("do not remove ref-only defs") { | ||||
|     IndexFile previous("foo.cc"); | ||||
|     IndexFile current("foo.cc"); | ||||
| 
 | ||||
|     previous.Resolve(previous.ToTypeId("usr1")) | ||||
|         ->uses.push_back(Range(Position(1, 0))); | ||||
|     previous.Resolve(previous.ToFuncId("usr2")) | ||||
|         ->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                         false /*is_implicit*/)); | ||||
|     previous.Resolve(previous.ToVarId("usr3")) | ||||
|         ->uses.push_back(Range(Position(3, 0))); | ||||
| 
 | ||||
|     IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|     REQUIRE(update.types_removed == std::vector<Usr>{}); | ||||
|     REQUIRE(update.funcs_removed == std::vector<Usr>{}); | ||||
|     REQUIRE(update.vars_removed == std::vector<Usr>{}); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("func callers") { | ||||
|     IndexFile previous("foo.cc"); | ||||
|     IndexFile current("foo.cc"); | ||||
| 
 | ||||
|     IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); | ||||
|     IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); | ||||
| 
 | ||||
|     pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), | ||||
|                                       false /*is_implicit*/)); | ||||
|     cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                       false /*is_implicit*/)); | ||||
| 
 | ||||
|     IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|     REQUIRE(update.funcs_removed == std::vector<Usr>{}); | ||||
|     REQUIRE(update.funcs_callers.size() == 1); | ||||
|     REQUIRE(update.funcs_callers[0].id == QueryFuncId(0)); | ||||
|     REQUIRE(update.funcs_callers[0].to_remove.size() == 1); | ||||
|     REQUIRE(update.funcs_callers[0].to_remove[0].loc.range == | ||||
|             Range(Position(1, 0))); | ||||
|     REQUIRE(update.funcs_callers[0].to_add.size() == 1); | ||||
|     REQUIRE(update.funcs_callers[0].to_add[0].loc.range == Range(Position(2, 0))); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("type usages") { | ||||
|     IndexFile previous("foo.cc"); | ||||
|     IndexFile current("foo.cc"); | ||||
| 
 | ||||
|     IndexType* pt = previous.Resolve(previous.ToTypeId("usr")); | ||||
|     IndexType* ct = current.Resolve(current.ToTypeId("usr")); | ||||
| 
 | ||||
|     pt->uses.push_back(Range(Position(1, 0))); | ||||
|     ct->uses.push_back(Range(Position(2, 0))); | ||||
| 
 | ||||
|     IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|     REQUIRE(update.types_removed == std::vector<Usr>{}); | ||||
|     REQUIRE(update.types_def_update == std::vector<QueryType::DefUpdate>{}); | ||||
|     REQUIRE(update.types_uses.size() == 1); | ||||
|     REQUIRE(update.types_uses[0].to_remove.size() == 1); | ||||
|     REQUIRE(update.types_uses[0].to_remove[0].range == Range(Position(1, 0))); | ||||
|     REQUIRE(update.types_uses[0].to_add.size() == 1); | ||||
|     REQUIRE(update.types_uses[0].to_add[0].range == Range(Position(2, 0))); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("apply delta") { | ||||
|     IndexFile previous("foo.cc"); | ||||
|     IndexFile current("foo.cc"); | ||||
| 
 | ||||
|     IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); | ||||
|     IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); | ||||
|     pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), | ||||
|                                       false /*is_implicit*/)); | ||||
|     pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                       false /*is_implicit*/)); | ||||
|     cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)), | ||||
|                                       false /*is_implicit*/)); | ||||
|     cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)), | ||||
|                                       false /*is_implicit*/)); | ||||
| 
 | ||||
|     QueryDatabase db; | ||||
|     IdMap previous_map(&db, previous.id_cache); | ||||
|     IdMap current_map(&db, current.id_cache); | ||||
|     REQUIRE(db.funcs.size() == 1); | ||||
| 
 | ||||
|     IndexUpdate import_update = | ||||
|         IndexUpdate::CreateDelta(nullptr, &previous_map, nullptr, &previous); | ||||
|     IndexUpdate delta_update = IndexUpdate::CreateDelta( | ||||
|         &previous_map, ¤t_map, &previous, ¤t); | ||||
| 
 | ||||
|     db.ApplyIndexUpdate(&import_update); | ||||
|     REQUIRE(db.funcs[0].callers.size() == 2); | ||||
|     REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(1, 0))); | ||||
|     REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(2, 0))); | ||||
| 
 | ||||
|     db.ApplyIndexUpdate(&delta_update); | ||||
|     REQUIRE(db.funcs[0].callers.size() == 2); | ||||
|     REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(4, 0))); | ||||
|     REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(5, 0))); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("remove defs") { | ||||
|   IndexFile previous("foo.cc"); | ||||
|   IndexFile current("foo.cc"); | ||||
| 
 | ||||
|   previous.Resolve(previous.ToTypeId("usr1"))->def.definition_spelling = | ||||
|       Range(Position(1, 0)); | ||||
|   previous.Resolve(previous.ToFuncId("usr2"))->def.definition_spelling = | ||||
|       Range(Position(2, 0)); | ||||
|   previous.Resolve(previous.ToVarId("usr3"))->def.definition_spelling = | ||||
|       Range(Position(3, 0)); | ||||
| 
 | ||||
|   IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|   REQUIRE(update.types_removed == std::vector<Usr>{"usr1"}); | ||||
|   REQUIRE(update.funcs_removed == std::vector<Usr>{"usr2"}); | ||||
|   REQUIRE(update.vars_removed == std::vector<Usr>{"usr3"}); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("do not remove ref-only defs") { | ||||
|   IndexFile previous("foo.cc"); | ||||
|   IndexFile current("foo.cc"); | ||||
| 
 | ||||
|   previous.Resolve(previous.ToTypeId("usr1")) | ||||
|       ->uses.push_back(Range(Position(1, 0))); | ||||
|   previous.Resolve(previous.ToFuncId("usr2")) | ||||
|       ->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                        false /*is_implicit*/)); | ||||
|   previous.Resolve(previous.ToVarId("usr3")) | ||||
|       ->uses.push_back(Range(Position(3, 0))); | ||||
| 
 | ||||
|   IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|   REQUIRE(update.types_removed == std::vector<Usr>{}); | ||||
|   REQUIRE(update.funcs_removed == std::vector<Usr>{}); | ||||
|   REQUIRE(update.vars_removed == std::vector<Usr>{}); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("func callers") { | ||||
|   IndexFile previous("foo.cc"); | ||||
|   IndexFile current("foo.cc"); | ||||
| 
 | ||||
|   IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); | ||||
|   IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); | ||||
| 
 | ||||
|   pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), | ||||
|                                      false /*is_implicit*/)); | ||||
|   cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                      false /*is_implicit*/)); | ||||
| 
 | ||||
|   IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|   REQUIRE(update.funcs_removed == std::vector<Usr>{}); | ||||
|   REQUIRE(update.funcs_callers.size() == 1); | ||||
|   REQUIRE(update.funcs_callers[0].id == QueryFuncId(0)); | ||||
|   REQUIRE(update.funcs_callers[0].to_remove.size() == 1); | ||||
|   REQUIRE(update.funcs_callers[0].to_remove[0].loc.range == | ||||
|           Range(Position(1, 0))); | ||||
|   REQUIRE(update.funcs_callers[0].to_add.size() == 1); | ||||
|   REQUIRE(update.funcs_callers[0].to_add[0].loc.range == Range(Position(2, 0))); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("type usages") { | ||||
|   IndexFile previous("foo.cc"); | ||||
|   IndexFile current("foo.cc"); | ||||
| 
 | ||||
|   IndexType* pt = previous.Resolve(previous.ToTypeId("usr")); | ||||
|   IndexType* ct = current.Resolve(current.ToTypeId("usr")); | ||||
| 
 | ||||
|   pt->uses.push_back(Range(Position(1, 0))); | ||||
|   ct->uses.push_back(Range(Position(2, 0))); | ||||
| 
 | ||||
|   IndexUpdate update = GetDelta(previous, current); | ||||
| 
 | ||||
|   REQUIRE(update.types_removed == std::vector<Usr>{}); | ||||
|   REQUIRE(update.types_def_update == std::vector<QueryType::DefUpdate>{}); | ||||
|   REQUIRE(update.types_uses.size() == 1); | ||||
|   REQUIRE(update.types_uses[0].to_remove.size() == 1); | ||||
|   REQUIRE(update.types_uses[0].to_remove[0].range == Range(Position(1, 0))); | ||||
|   REQUIRE(update.types_uses[0].to_add.size() == 1); | ||||
|   REQUIRE(update.types_uses[0].to_add[0].range == Range(Position(2, 0))); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("apply delta") { | ||||
|   IndexFile previous("foo.cc"); | ||||
|   IndexFile current("foo.cc"); | ||||
| 
 | ||||
|   IndexFunc* pf = previous.Resolve(previous.ToFuncId("usr")); | ||||
|   IndexFunc* cf = current.Resolve(current.ToFuncId("usr")); | ||||
|   pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(1, 0)), | ||||
|                                      false /*is_implicit*/)); | ||||
|   pf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(2, 0)), | ||||
|                                      false /*is_implicit*/)); | ||||
|   cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(4, 0)), | ||||
|                                      false /*is_implicit*/)); | ||||
|   cf->callers.push_back(IndexFuncRef(IndexFuncId(0), Range(Position(5, 0)), | ||||
|                                      false /*is_implicit*/)); | ||||
| 
 | ||||
|   QueryDatabase db; | ||||
|   IdMap previous_map(&db, previous.id_cache); | ||||
|   IdMap current_map(&db, current.id_cache); | ||||
|   REQUIRE(db.funcs.size() == 1); | ||||
| 
 | ||||
|   IndexUpdate import_update = | ||||
|       IndexUpdate::CreateDelta(nullptr, &previous_map, nullptr, &previous); | ||||
|   IndexUpdate delta_update = IndexUpdate::CreateDelta( | ||||
|       &previous_map, ¤t_map, &previous, ¤t); | ||||
| 
 | ||||
|   db.ApplyIndexUpdate(&import_update); | ||||
|   REQUIRE(db.funcs[0].callers.size() == 2); | ||||
|   REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(1, 0))); | ||||
|   REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(2, 0))); | ||||
| 
 | ||||
|   db.ApplyIndexUpdate(&delta_update); | ||||
|   REQUIRE(db.funcs[0].callers.size() == 2); | ||||
|   REQUIRE(db.funcs[0].callers[0].loc.range == Range(Position(4, 0))); | ||||
|   REQUIRE(db.funcs[0].callers[1].loc.range == Range(Position(5, 0))); | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
| @ -379,107 +379,105 @@ std::vector<CXUnsavedFile> WorkingFiles::AsUnsavedFiles() { | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE("WorkingFile"); | ||||
| 
 | ||||
| lsPosition CharPos(const WorkingFile& file, | ||||
|                    char character, | ||||
|                    int character_offset = 0) { | ||||
|                   char character, | ||||
|                   int character_offset = 0) { | ||||
|   return CharPos(file.buffer_content, character, character_offset); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("simple call") { | ||||
|   WorkingFile f("foo.cc", "abcd(1, 2"); | ||||
|   int active_param = 0; | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '1'), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 1); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 1); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '2'), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 1); | ||||
| TEST_SUITE("WorkingFile") { | ||||
|   TEST_CASE("simple call") { | ||||
|     WorkingFile f("foo.cc", "abcd(1, 2"); | ||||
|     int active_param = 0; | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '1'), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 1); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 1); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '2'), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 1); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("nested call") { | ||||
|     WorkingFile f("foo.cc", "abcd(efg(), 2"); | ||||
|     int active_param = 0; | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'e'), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'f'), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g'), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 1), &active_param) == | ||||
|             "efg"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 2), &active_param) == | ||||
|             "efg"); | ||||
|     REQUIRE(active_param == 0); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 1); | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == | ||||
|             "abcd"); | ||||
|     REQUIRE(active_param == 1); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("auto-insert )") { | ||||
|     WorkingFile f("foo.cc", "abc()"); | ||||
|     int active_param = 0; | ||||
|     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ')'), &active_param) == | ||||
|             "abc"); | ||||
|     REQUIRE(active_param == 0); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("existing completion") { | ||||
|     WorkingFile f("foo.cc", "zzz.asdf"); | ||||
|     bool is_global_completion; | ||||
|     std::string existing_completion; | ||||
| 
 | ||||
|     f.FindStableCompletionSource(CharPos(f, '.'), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "zzz"); | ||||
|     f.FindStableCompletionSource(CharPos(f, 'a', 1), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "a"); | ||||
|     f.FindStableCompletionSource(CharPos(f, 's', 1), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "as"); | ||||
|     f.FindStableCompletionSource(CharPos(f, 'd', 1), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "asd"); | ||||
|     f.FindStableCompletionSource(CharPos(f, 'f', 1), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "asdf"); | ||||
|   } | ||||
| 
 | ||||
|   TEST_CASE("existing completion underscore") { | ||||
|     WorkingFile f("foo.cc", "ABC_DEF"); | ||||
|     bool is_global_completion; | ||||
|     std::string existing_completion; | ||||
| 
 | ||||
|     f.FindStableCompletionSource(CharPos(f, 'C'), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "AB"); | ||||
|     f.FindStableCompletionSource(CharPos(f, '_'), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "ABC"); | ||||
|     f.FindStableCompletionSource(CharPos(f, 'D'), &is_global_completion, | ||||
|                                 &existing_completion); | ||||
|     REQUIRE(existing_completion == "ABC_"); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("nested call") { | ||||
|   WorkingFile f("foo.cc", "abcd(efg(), 2"); | ||||
|   int active_param = 0; | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'e'), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'f'), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g'), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 1), &active_param) == | ||||
|           "efg"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, 'g', 2), &active_param) == | ||||
|           "efg"); | ||||
|   REQUIRE(active_param == 0); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 1); | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == | ||||
|           "abcd"); | ||||
|   REQUIRE(active_param == 1); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("auto-insert )") { | ||||
|   WorkingFile f("foo.cc", "abc()"); | ||||
|   int active_param = 0; | ||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ')'), &active_param) == | ||||
|           "abc"); | ||||
|   REQUIRE(active_param == 0); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("existing completion") { | ||||
|   WorkingFile f("foo.cc", "zzz.asdf"); | ||||
|   bool is_global_completion; | ||||
|   std::string existing_completion; | ||||
| 
 | ||||
|   f.FindStableCompletionSource(CharPos(f, '.'), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "zzz"); | ||||
|   f.FindStableCompletionSource(CharPos(f, 'a', 1), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "a"); | ||||
|   f.FindStableCompletionSource(CharPos(f, 's', 1), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "as"); | ||||
|   f.FindStableCompletionSource(CharPos(f, 'd', 1), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "asd"); | ||||
|   f.FindStableCompletionSource(CharPos(f, 'f', 1), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "asdf"); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("existing completion underscore") { | ||||
|   WorkingFile f("foo.cc", "ABC_DEF"); | ||||
|   bool is_global_completion; | ||||
|   std::string existing_completion; | ||||
| 
 | ||||
|   f.FindStableCompletionSource(CharPos(f, 'C'), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "AB"); | ||||
|   f.FindStableCompletionSource(CharPos(f, '_'), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "ABC"); | ||||
|   f.FindStableCompletionSource(CharPos(f, 'D'), &is_global_completion, | ||||
|                                &existing_completion); | ||||
|   REQUIRE(existing_completion == "ABC_"); | ||||
| } | ||||
| 
 | ||||
| TEST_SUITE_END(); | ||||
|  | ||||
							
								
								
									
										2
									
								
								third_party/doctest
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								third_party/doctest
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| Subproject commit 11147357234d0166c9ec96c4d9e328464b884da3 | ||||
| Subproject commit 79a379827251cd819c5286070834ccd0ac628af9 | ||||
							
								
								
									
										2
									
								
								third_party/loguru
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								third_party/loguru
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| Subproject commit ac23215b4b9e878dfe5c2fd3d4afbf7a63cdad12 | ||||
| Subproject commit 83b6f3c3d16e40453ec0d12d3baef42cd2f37c3b | ||||
							
								
								
									
										2
									
								
								third_party/rapidjson
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								third_party/rapidjson
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| Subproject commit 0163a53f4a1c72e6a05848a63d80eee0d8e3f387 | ||||
| Subproject commit 17ae6ffa857173c25708e61610121bc908c0a6cd | ||||
							
								
								
									
										2
									
								
								third_party/sparsepp
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								third_party/sparsepp
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| Subproject commit b1d54fbe547cab3a13d181f16f1de758d6827f81 | ||||
| Subproject commit bfb0de71ee7fa12a5f12c3ef61ce9f1d6d86d907 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user