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") { |     LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, | ||||||
|   std::string buffer_content = " void Foo(); "; |                           &newlines_after_name); | ||||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); |     REQUIRE(insert_text == "void Foo() {\n}"); | ||||||
|   std::string insert_text; |     REQUIRE(newlines_after_name == 0); | ||||||
|   int newlines_after_name = 0; |  | ||||||
| 
 | 
 | ||||||
|   LexFunctionDeclaration(buffer_content, declaration, nullopt, &insert_text, |     LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), | ||||||
|                          &newlines_after_name); |                           &insert_text, &newlines_after_name); | ||||||
|   REQUIRE(insert_text == "void Foo() {\n}"); |     REQUIRE(insert_text == "void Type::Foo() {\n}"); | ||||||
|   REQUIRE(newlines_after_name == 0); |     REQUIRE(newlines_after_name == 0); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Type"), |   TEST_CASE("ctor") { | ||||||
|                          &insert_text, &newlines_after_name); |     std::string buffer_content = " Foo(); "; | ||||||
|   REQUIRE(insert_text == "void Type::Foo() {\n}"); |     lsPosition declaration = CharPos(buffer_content, 'F'); | ||||||
|   REQUIRE(newlines_after_name == 0); |     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") { | TEST_SUITE("LexWordAroundPos") { | ||||||
|   std::string buffer_content = " Foo(); "; |   TEST_CASE("edges") { | ||||||
|   lsPosition declaration = CharPos(buffer_content, 'F'); |     std::string content = "Foobar"; | ||||||
|   std::string insert_text; |     REQUIRE(LexWordAroundPos(CharPos(content, 'F'), content) == "Foobar"); | ||||||
|   int newlines_after_name = 0; |     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"), |   TEST_CASE("simple") { | ||||||
|                          &insert_text, &newlines_after_name); |     std::string content = "  Foobar  "; | ||||||
|   REQUIRE(insert_text == "Foo::Foo() {\n}"); |     REQUIRE(LexWordAroundPos(CharPos(content, 'F'), content) == "Foobar"); | ||||||
|   REQUIRE(newlines_after_name == 0); |     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") { | TEST_SUITE("FindIncludeLine") { | ||||||
|   std::string buffer_content = " ~Foo(); "; |   TEST_CASE("in document") { | ||||||
|   lsPosition declaration = CharPos(buffer_content, '~'); |     std::vector<std::string> lines = { | ||||||
|   std::string insert_text; |         "#include <bbb>",  // 0
 | ||||||
|   int newlines_after_name = 0; |         "#include <ddd>"   // 1
 | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|   LexFunctionDeclaration(buffer_content, declaration, std::string("Foo"), |     REQUIRE(FindIncludeLine(lines, "#include <bbb>") == nullopt); | ||||||
|                          &insert_text, &newlines_after_name); |   } | ||||||
|   REQUIRE(insert_text == "Foo::~Foo() {\n}"); | 
 | ||||||
|   REQUIRE(newlines_after_name == 0); |   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; |   return content; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_SUITE("FindIncludeLine"); |  | ||||||
| 
 |  | ||||||
| std::function<optional<char>()> MakeContentReader(std::string* content, | std::function<optional<char>()> MakeContentReader(std::string* content, | ||||||
|                                                   bool can_be_empty) { |                                                   bool can_be_empty) { | ||||||
|   return [content, can_be_empty]() -> optional<char> { |   return [content, can_be_empty]() -> optional<char> { | ||||||
| @ -97,31 +95,31 @@ std::function<optional<char>()> MakeContentReader(std::string* content, | |||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("ReadContentFromSource") { | TEST_SUITE("FindIncludeLine") { | ||||||
|   auto parse_correct = [](std::string content) -> std::string { |   TEST_CASE("ReadContentFromSource") { | ||||||
|     auto reader = MakeContentReader(&content, false /*can_be_empty*/); |     auto parse_correct = [](std::string content) -> std::string { | ||||||
|     auto got = ReadJsonRpcContentFrom(reader); |       auto reader = MakeContentReader(&content, false /*can_be_empty*/); | ||||||
|     REQUIRE(got); |       auto got = ReadJsonRpcContentFrom(reader); | ||||||
|     return got.value(); |       REQUIRE(got); | ||||||
|   }; |       return got.value(); | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|   auto parse_incorrect = [](std::string content) -> optional<std::string> { |     auto parse_incorrect = [](std::string content) -> optional<std::string> { | ||||||
|     auto reader = MakeContentReader(&content, true /*can_be_empty*/); |       auto reader = MakeContentReader(&content, true /*can_be_empty*/); | ||||||
|     return ReadJsonRpcContentFrom(reader); |       return ReadJsonRpcContentFrom(reader); | ||||||
|   }; |     }; | ||||||
| 
 | 
 | ||||||
|   REQUIRE(parse_correct("Content-Length: 0\r\n\r\n") == ""); |     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: 1\r\n\r\na") == "a"); | ||||||
|   REQUIRE(parse_correct("Content-Length: 4\r\n\r\nabcd") == "abcd"); |     REQUIRE(parse_correct("Content-Length: 4\r\n\r\nabcd") == "abcd"); | ||||||
| 
 | 
 | ||||||
|   REQUIRE(parse_incorrect("ggg") == 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: 0\r\n") == optional<std::string>()); | ||||||
|   REQUIRE(parse_incorrect("Content-Length: 5\r\n\r\nab") == |     REQUIRE(parse_incorrect("Content-Length: 5\r\n\r\nab") == | ||||||
|           optional<std::string>()); |             optional<std::string>()); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_SUITE_END(); |  | ||||||
| 
 |  | ||||||
| optional<char> ReadCharFromStdinBlocking() { | optional<char> ReadCharFromStdinBlocking() { | ||||||
|   // Bad stdin means parent process has probably exited. Either way, cquery
 |   // Bad stdin means parent process has probably exited. Either way, cquery
 | ||||||
|   // can no longer be communicated with so just exit.
 |   // 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; |   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") { |   TEST_CASE("in middle of content") { | ||||||
|   std::string content = "foo"; |     std::string content = "abcdefghijk"; | ||||||
|   int offset = GetOffsetForPosition(lsPosition(10, 10), content); |     for (int i = 0; i < content.size(); ++i) { | ||||||
|   REQUIRE(offset <= content.size()); |       int offset = GetOffsetForPosition(lsPosition(0, i), content); | ||||||
| } |       REQUIRE(i == offset); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("in middle of content") { |   TEST_CASE("at end of content") { | ||||||
|   std::string content = "abcdefghijk"; |     REQUIRE(GetOffsetForPosition(lsPosition(0, 0), "") == 0); | ||||||
|   for (int i = 0; i < content.size(); ++i) { |     REQUIRE(GetOffsetForPosition(lsPosition(0, 1), "a") == 1); | ||||||
|     int offset = GetOffsetForPosition(lsPosition(0, i), content); |  | ||||||
|     REQUIRE(i == offset); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("at end of content") { | TEST_SUITE("Substring") { | ||||||
|   REQUIRE(GetOffsetForPosition(lsPosition(0, 0), "") == 0); |   TEST_CASE("match") { | ||||||
|   REQUIRE(GetOffsetForPosition(lsPosition(0, 1), "a") == 1); |     // 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; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_SUITE("Matcher"); | TEST_SUITE("Matcher") { | ||||||
| 
 |   TEST_CASE("sanity") { | ||||||
| TEST_CASE("sanity") { |     // Matcher m("abc");
 | ||||||
|   // Matcher m("abc");
 |     // TODO: check case
 | ||||||
|   // TODO: check case
 |     // CHECK(m.IsMatch("abc"));
 | ||||||
|   // CHECK(m.IsMatch("abc"));
 |     // CHECK(m.IsMatch("fooabc"));
 | ||||||
|   // CHECK(m.IsMatch("fooabc"));
 |     // CHECK(m.IsMatch("abc"));
 | ||||||
|   // CHECK(m.IsMatch("abc"));
 |     // CHECK(m.IsMatch("abcfoo"));
 | ||||||
|   // CHECK(m.IsMatch("abcfoo"));
 |     // CHECK(m.IsMatch("11a11b11c11"));
 | ||||||
|   // 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") { |   TEST_CASE("Mutex lock/unlock (single process)") { | ||||||
|   std::vector<std::string> actual = Split("/a/b/c/", '/'); |     auto m1 = CreatePlatformMutex("indexer-platformmutexttest"); | ||||||
|   std::vector<std::string> expected{"a", "b", "c"}; |     auto l1 = CreatePlatformScopedMutexLock(m1.get()); | ||||||
|   REQUIRE(actual == expected); |     auto m2 = CreatePlatformMutex("indexer-platformmutexttest"); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| TEST_CASE("Mutex lock/unlock (single process)") { |     int value = 0; | ||||||
|   auto m1 = CreatePlatformMutex("indexer-platformmutexttest"); |  | ||||||
|   auto l1 = CreatePlatformScopedMutexLock(m1.get()); |  | ||||||
|   auto m2 = CreatePlatformMutex("indexer-platformmutexttest"); |  | ||||||
| 
 | 
 | ||||||
|   int value = 0; |     volatile bool did_run = false; | ||||||
| 
 |     std::thread t([&]() { | ||||||
|   volatile bool did_run = false; |       did_run = true; | ||||||
|   std::thread t([&]() { |       auto l2 = CreatePlatformScopedMutexLock(m2.get()); | ||||||
|     did_run = true; |       value = 1; | ||||||
|     auto l2 = CreatePlatformScopedMutexLock(m2.get()); |     }); | ||||||
|     value = 1; |     while (!did_run) | ||||||
|   }); |       std::this_thread::sleep_for(std::chrono::milliseconds(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
 |     // Other thread has had a chance to run, but it should not have
 | ||||||
|   // written to value yet (ie, it should be waiting).
 |     // written to value yet (ie, it should be waiting).
 | ||||||
|   REQUIRE(value == 0); |     REQUIRE(value == 0); | ||||||
| 
 | 
 | ||||||
|   // Release the lock, wait for other thread to finish. Verify it
 |     // Release the lock, wait for other thread to finish. Verify it
 | ||||||
|   // wrote the expected value.
 |     // wrote the expected value.
 | ||||||
|   l1.reset(); |     l1.reset(); | ||||||
|   t.join(); |     t.join(); | ||||||
|   REQUIRE(value == 1); |     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) { |   TEST_CASE("remove defs") { | ||||||
|   QueryDatabase db; |     IndexFile previous("foo.cc"); | ||||||
|   IdMap previous_map(&db, previous.id_cache); |     IndexFile current("foo.cc"); | ||||||
|   IdMap current_map(&db, current.id_cache); | 
 | ||||||
|   return IndexUpdate::CreateDelta(&previous_map, ¤t_map, &previous, |     previous.Resolve(previous.ToTypeId("usr1"))->def.definition_spelling = | ||||||
|                                   ¤t); |         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; |   return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_SUITE("WorkingFile"); |  | ||||||
| 
 |  | ||||||
| lsPosition CharPos(const WorkingFile& file, | lsPosition CharPos(const WorkingFile& file, | ||||||
|                    char character, |                   char character, | ||||||
|                    int character_offset = 0) { |                   int character_offset = 0) { | ||||||
|   return CharPos(file.buffer_content, character, character_offset); |   return CharPos(file.buffer_content, character, character_offset); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("simple call") { | TEST_SUITE("WorkingFile") { | ||||||
|   WorkingFile f("foo.cc", "abcd(1, 2"); |   TEST_CASE("simple call") { | ||||||
|   int active_param = 0; |     WorkingFile f("foo.cc", "abcd(1, 2"); | ||||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == |     int active_param = 0; | ||||||
|           "abcd"); |     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '('), &active_param) == | ||||||
|   REQUIRE(active_param == 0); |             "abcd"); | ||||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '1'), &active_param) == |     REQUIRE(active_param == 0); | ||||||
|           "abcd"); |     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '1'), &active_param) == | ||||||
|   REQUIRE(active_param == 0); |             "abcd"); | ||||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == |     REQUIRE(active_param == 0); | ||||||
|           "abcd"); |     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ','), &active_param) == | ||||||
|   REQUIRE(active_param == 1); |             "abcd"); | ||||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == |     REQUIRE(active_param == 1); | ||||||
|           "abcd"); |     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, ' '), &active_param) == | ||||||
|   REQUIRE(active_param == 1); |             "abcd"); | ||||||
|   REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '2'), &active_param) == |     REQUIRE(active_param == 1); | ||||||
|           "abcd"); |     REQUIRE(f.FindClosestCallNameInBuffer(CharPos(f, '2'), &active_param) == | ||||||
|   REQUIRE(active_param == 1); |             "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