logic: name qualifiers of symbols are clickable now
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "helper/DumpParserClient.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
#include "utility/file/FileRegister.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
#include "utility/utility.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
@@ -146,6 +147,6 @@ private:
|
||||
|
||||
parser.buildIndex(command);
|
||||
|
||||
return TextAccess::createFromString(parserClient->m_dump);
|
||||
return TextAccess::createFromString(parserClient->m_lines);
|
||||
}
|
||||
};
|
||||
@@ -1280,6 +1280,94 @@ public:
|
||||
));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test qualifier locations
|
||||
|
||||
void test_cxx_parser_finds_qualifier_of_access_to_global_variable_defined_in_namespace()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"namespace foo {\n"
|
||||
" namespace bar {\n"
|
||||
" int x;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"void f() {\n"
|
||||
" foo::bar::x = 9;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "foo <7:2 7:4>"));
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "foo::bar <7:7 7:9>"));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_qualifier_of_access_to_static_field()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"class Foo {\n"
|
||||
"public:\n"
|
||||
" struct Bar {\n"
|
||||
" public:\n"
|
||||
" static int x;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
"void f() {\n"
|
||||
" Foo::Bar::x = 9;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "Foo <9:2 9:4>"));
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "Foo::Bar <9:7 9:9>"));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_qualifier_of_access_to_enum_constant()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"enum Foo {\n"
|
||||
" FOO_V\n"
|
||||
"};\n"
|
||||
"void f() {\n"
|
||||
" Foo v = Foo::FOO_V;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "Foo <5:10 5:12>"));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_qualifier_of_reference_to_method()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"class Foo {\n"
|
||||
"public:\n"
|
||||
" static void my_int_func(int x) {\n"
|
||||
" }\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void test() {\n"
|
||||
" void(*foo)(int);\n"
|
||||
" foo = &Foo::my_int_func;\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "Foo <9:9 9:11>"));
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_qualifier_of_constructor_call()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"class Foo {\n"
|
||||
"public:\n"
|
||||
" Foo(int i) {}\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"class Bar : public Foo {\n"
|
||||
"public:\n"
|
||||
" Bar() : Foo::Foo(4) {}\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(client->qualifiers, "Foo <8:10 8:12>"));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test implicit symbols
|
||||
|
||||
|
||||
@@ -264,6 +264,6 @@ private:
|
||||
|
||||
parser.buildIndex(command);
|
||||
|
||||
return TextAccess::createFromString(parserClient->m_dump);
|
||||
return TextAccess::createFromString(parserClient->m_lines);
|
||||
}
|
||||
};
|
||||
@@ -462,6 +462,311 @@ public:
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test finding qualifier locations
|
||||
|
||||
void test_java_parser_finds_no_qualifier_location_of_standalone_this_expression()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"public class X\n"
|
||||
"{\n"
|
||||
" public void bar()\n"
|
||||
" {\n"
|
||||
" X x = this;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->qualifiers.size(), 0);
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_import_declaration()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"import foo.bar;\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo <1:8 1:10>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_simple_type()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo.bar;\n"
|
||||
"public class A\n"
|
||||
"{\n"
|
||||
" public void bar(int i)\n"
|
||||
" {\n"
|
||||
" foo.bar.A a;\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo <6:3 6:5>"
|
||||
));
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.bar <6:7 6:9>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_field_access()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"public class X\n"
|
||||
"{\n"
|
||||
" public int i;\n"
|
||||
" \n"
|
||||
" public void bar()\n"
|
||||
" {\n"
|
||||
" this.i = 9;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.X <8:3 8:6>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_super_field_access()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class B extends A\n"
|
||||
"{\n"
|
||||
" void foo()\n"
|
||||
" {\n"
|
||||
" B.super.a = 0;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.B <11:3 11:3>"
|
||||
));
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.A <11:5 11:9>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_this_expression()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" int a;\n"
|
||||
" \n"
|
||||
" void foo()\n"
|
||||
" {\n"
|
||||
" A a = A.this;"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.A <8:9 8:9>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_method_invocation()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"public class X\n"
|
||||
"{\n"
|
||||
" public static void bar()\n"
|
||||
" {\n"
|
||||
" foo.X.bar();\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo <6:3 6:5>"
|
||||
));
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.X <6:7 6:7>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_method_invocation_on_this()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"public class X\n"
|
||||
"{\n"
|
||||
" public void bar()\n"
|
||||
" {\n"
|
||||
" this.bar();\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.X <6:3 6:6>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_super_method_invocation()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"package foo;\n"
|
||||
"public class X\n"
|
||||
"{\n"
|
||||
" public class A\n"
|
||||
" {\n"
|
||||
" void bar()\n"
|
||||
" {\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" public class B extends A\n"
|
||||
" {\n"
|
||||
" void bar()\n"
|
||||
" {\n"
|
||||
" foo.X.B.super.bar();\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo <15:4 15:6>"
|
||||
));
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.X <15:8 15:8>"
|
||||
));
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.X.B <15:10 15:10>"
|
||||
));
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "foo.X.A <15:12 15:16>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_creation_reference()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"public class A\n"
|
||||
"{\n"
|
||||
" public interface Functor\n"
|
||||
" {\n"
|
||||
" public void doSomething();\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" public class Bar\n"
|
||||
" {\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" void foo()\n"
|
||||
" {\n"
|
||||
" Functor method = A.Bar::new;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "A <14:20 14:20>"
|
||||
));
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "A.Bar <14:22 14:24>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_expression_method_reference()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"public class A\n"
|
||||
"{\n"
|
||||
" public interface Functor\n"
|
||||
" {\n"
|
||||
" public void doSomething();\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" public class B\n"
|
||||
" {\n"
|
||||
" void bar()\n"
|
||||
" {\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" void foo()\n"
|
||||
" {\n"
|
||||
" Functor method = B::bar;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "A.B <17:20 17:20>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_super_method_reference()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"public class A {\n"
|
||||
" public interface Functor {\n"
|
||||
" public void doSomething();\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" public class B {\n"
|
||||
" void bar() {\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" public class C extends B {\n"
|
||||
" void foo() {\n"
|
||||
" Functor method = super::bar;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "A.B <13:21 13:25>"
|
||||
));
|
||||
}
|
||||
|
||||
void test_java_parser_finds_qualifier_location_of_class_instance_creation()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"public class A {\n"
|
||||
" public interface Functor {\n"
|
||||
" public void doSomething();\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" public class B {\n"
|
||||
" void bar() {\n"
|
||||
" B b = new A.B();"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->qualifiers, "A <8:14 8:14>"
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test finding usages of symbols
|
||||
|
||||
@@ -578,7 +883,7 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT(utility::containsElement<std::string>(
|
||||
client->typeUses, "void A.bar() -> A.B <8:3 8:5>"
|
||||
client->typeUses, "void A.bar() -> A.B <8:5 8:5>"
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -10,39 +10,39 @@ class DumpParserClient : public ParserClient
|
||||
{
|
||||
public:
|
||||
DumpParserClient()
|
||||
: m_dump("")
|
||||
: m_lines("")
|
||||
{
|
||||
}
|
||||
|
||||
virtual Id recordSymbol(
|
||||
const NameHierarchy& symbolName, SymbolKind symbolKind,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
AccessKind access, DefinitionKind definitionKind) override
|
||||
{
|
||||
m_dump += symbolKindToString(symbolKind) + " " + addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + "\n";
|
||||
recordLine(symbolKindToString(symbolKind) + " " + addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id recordSymbol(
|
||||
const NameHierarchy& symbolName, SymbolKind symbolKind,
|
||||
const ParseLocation& location,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
AccessKind access, DefinitionKind definitionKind) override
|
||||
{
|
||||
m_dump += symbolKindToString(symbolKind) + " " + addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
recordLine(symbolKindToString(symbolKind) + " " + addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + " [" + location.filePath.fileName(), location) + "]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id recordSymbol(
|
||||
const NameHierarchy& symbolName, SymbolKind symbolKind,
|
||||
const ParseLocation& location, const ParseLocation& scopeLocation,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
AccessKind access, DefinitionKind definitionKind) override
|
||||
{
|
||||
m_dump += symbolKindToString(symbolKind) + " " + addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + " [" + location.filePath.fileName(), location, scopeLocation) + "]\n";
|
||||
recordLine(symbolKindToString(symbolKind) + " " + addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access) + " [" + location.filePath.fileName(), location, scopeLocation) + "]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void recordReference(
|
||||
ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName,
|
||||
const ParseLocation& location)
|
||||
const ParseLocation& location) override
|
||||
{
|
||||
std::string contextNameString = contextName.getQualifiedNameWithSignature();
|
||||
try
|
||||
@@ -56,33 +56,47 @@ public:
|
||||
{
|
||||
// do nothing and use the old contectNameString
|
||||
}
|
||||
m_dump += referenceKindToString(referenceKind) + " " + addLocationSuffix(contextNameString + " -> " + referencedName.getQualifiedNameWithSignature() + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
recordLine(referenceKindToString(referenceKind) + " " + addLocationSuffix(contextNameString + " -> " + referencedName.getQualifiedNameWithSignature() + " [" + location.filePath.fileName(), location) + "]\n");
|
||||
}
|
||||
|
||||
void recordQualifierLocation(const NameHierarchy& qualifierName, const ParseLocation& location) override
|
||||
{
|
||||
recordLine("QUALIFIER: " + addLocationSuffix(qualifierName.getQualifiedNameWithSignature() + " [" + location.filePath.fileName(), location) + "]\n");
|
||||
}
|
||||
|
||||
virtual void onError(const ParseLocation& location, const std::string& message, const std::string& commandline,
|
||||
bool fatal, bool indexed)
|
||||
bool fatal, bool indexed) override
|
||||
{
|
||||
m_dump += "ERROR: " + addLocationSuffix(message + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
recordLine("ERROR: " + addLocationSuffix(message + " [" + location.filePath.fileName(), location) + "]\n");
|
||||
}
|
||||
|
||||
virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location)
|
||||
virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location) override
|
||||
{
|
||||
m_dump += "LOCAL_SYMBOL: " + addLocationSuffix(name + " [" + location.filePath.fileName(), location) + "]\n";
|
||||
recordLine("LOCAL_SYMBOL: " + addLocationSuffix(name + " [" + location.filePath.fileName(), location) + "]\n");
|
||||
}
|
||||
|
||||
virtual void onFileParsed(const FileInfo& fileInfo)
|
||||
virtual void onFileParsed(const FileInfo& fileInfo) override
|
||||
{
|
||||
m_dump += "FILE: " + fileInfo.path.fileName() + "\n";
|
||||
recordLine("FILE: " + fileInfo.path.fileName() + "\n");
|
||||
}
|
||||
|
||||
virtual void onCommentParsed(const ParseLocation& location)
|
||||
virtual void onCommentParsed(const ParseLocation& location) override
|
||||
{
|
||||
m_dump += "COMMENT: " + addLocationSuffix("comment [" + location.filePath.fileName(), location) + "]\n";
|
||||
recordLine("COMMENT: " + addLocationSuffix("comment [" + location.filePath.fileName(), location) + "]\n");
|
||||
}
|
||||
|
||||
std::string m_dump;
|
||||
std::string m_lines;
|
||||
|
||||
private:
|
||||
void recordLine(const std::string& message)
|
||||
{
|
||||
if (m_recordedLines.find(message) == m_recordedLines.end())
|
||||
{
|
||||
m_recordedLines.insert(message);
|
||||
m_lines += message;
|
||||
}
|
||||
}
|
||||
|
||||
std::string symbolKindToString(SymbolKind symbolKind) const
|
||||
{
|
||||
switch (symbolKind)
|
||||
@@ -162,6 +176,8 @@ private:
|
||||
}
|
||||
return "REFERENCE_UNDEFINED";
|
||||
}
|
||||
|
||||
std::set<std::string> m_recordedLines;
|
||||
};
|
||||
|
||||
#endif // DUMP_PARSER_CLIENT_H
|
||||
|
||||
@@ -102,6 +102,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void recordQualifierLocation(
|
||||
const NameHierarchy& qualifierName, const ParseLocation& location)
|
||||
{
|
||||
qualifiers.push_back(addLocationSuffix(qualifierName.getQualifiedNameWithSignature(), location));
|
||||
}
|
||||
|
||||
virtual void onError(const ParseLocation& location, const std::string& message, const std::string& commandline,
|
||||
bool fatal, bool indexed)
|
||||
{
|
||||
@@ -124,6 +130,7 @@ public:
|
||||
}
|
||||
|
||||
std::vector<std::string> errors;
|
||||
std::vector<std::string> qualifiers;
|
||||
|
||||
std::vector<std::string> packages;
|
||||
std::vector<std::string> typedefs;
|
||||
|
||||
Reference in New Issue
Block a user