logic: index and store Java annotations

* add annotation symbol kind
* add annotation_usage edge kind
* increment storage version
* record java annotation decls
* record java annotation member decls (as fields)
* update expected output of java sample project indexing tests
* add tests for recording annotations
* add annotation icon, annotation colors
* add new annotation node and edge types to legend
This commit is contained in:
mlangkabel
2018-08-14 17:33:00 +02:00
parent abe0248c1e
commit 9813c9873f
116 changed files with 1184 additions and 88 deletions
@@ -2377,6 +2377,7 @@ void GraphController::createLegendGraph()
incompleteFile->addComponent(std::make_shared<TokenComponentFilePath>(FilePath(), false));
addNode(NodeType::NODE_MACRO, L"Macro", Vec2i(x, y + dy * ++i));
addNode(NodeType::NODE_ANNOTATION, L"Annotation", Vec2i(x, y + dy * ++i));
addNode(NodeType::NODE_NAMESPACE, L"namespace", Vec2i(x, y + dy * ++i));
y -= 15;
@@ -2488,6 +2489,13 @@ void GraphController::createLegendGraph()
addEdge(Edge::EDGE_MACRO_USAGE, file, macro);
}
{
addText(L"annotation use", 0, Vec2i(x, y + dy * ++i));
Node* type = addNode(NodeType::NODE_TYPE, L"Type", Vec2i(x, y + dy * ++i));
Node* macro = addNode(NodeType::NODE_ANNOTATION, L"Annotation", Vec2i(x + dx, y + dy * i));
addEdge(Edge::EDGE_ANNOTATION_USAGE, type, macro);
}
{
addText(L"aggregation", 0, Vec2i(x, y + dy * ++i));
Node* typeA = addNode(NodeType::NODE_TYPE, L"Type A", Vec2i(x, y + dy * ++i));
+15
View File
@@ -8,6 +8,7 @@ std::vector<NodeType> NodeType::getOverviewBundleNodeTypesOrdered()
return {
NodeType(NodeType::NODE_FILE),
NodeType(NodeType::NODE_MACRO),
NodeType(NodeType::NODE_ANNOTATION),
NodeType(NodeType::NODE_NAMESPACE),
NodeType(NodeType::NODE_PACKAGE),
NodeType(NodeType::NODE_CLASS),
@@ -45,6 +46,8 @@ NodeType::Type NodeType::intToType(int value)
return NodeType::NODE_CLASS;
case NodeType::NODE_INTERFACE:
return NodeType::NODE_INTERFACE;
case NodeType::NODE_ANNOTATION:
return NodeType::NODE_ANNOTATION;
case NodeType::NODE_GLOBAL_VARIABLE:
return NodeType::NODE_GLOBAL_VARIABLE;
case NodeType::NODE_FIELD:
@@ -94,6 +97,8 @@ std::string NodeType::getReadableTypeString(NodeType::Type type)
return "class";
case NodeType::NODE_INTERFACE:
return "interface";
case NodeType::NODE_ANNOTATION:
return "annotation";
case NodeType::NODE_GLOBAL_VARIABLE:
return "global variable";
case NodeType::NODE_FIELD:
@@ -237,6 +242,7 @@ bool NodeType::isUsable() const
NodeType::NODE_ENUM |
NodeType::NODE_UNION |
NodeType::NODE_INTERFACE |
NodeType::NODE_ANNOTATION |
NodeType::NODE_TYPEDEF;
return ((m_type & mask) > 0);
}
@@ -248,6 +254,7 @@ bool NodeType::isPotentialMember() const
NodeType::NODE_FIELD |
NodeType::NODE_CLASS |
NodeType::NODE_INTERFACE |
NodeType::NODE_ANNOTATION |
NodeType::NODE_STRUCT |
NodeType::NODE_UNION |
NodeType::NODE_TYPEDEF |
@@ -265,6 +272,7 @@ bool NodeType::isCollapsible() const
NodeType::NODE_STRUCT |
NodeType::NODE_CLASS |
NodeType::NODE_INTERFACE |
NodeType::NODE_ANNOTATION |
NodeType::NODE_ENUM |
NodeType::NODE_UNION |
NodeType::NODE_FILE;
@@ -285,6 +293,7 @@ bool NodeType::hasSearchFilter() const
NodeType::NODE_STRUCT |
NodeType::NODE_CLASS |
NodeType::NODE_INTERFACE |
NodeType::NODE_ANNOTATION |
NodeType::NODE_GLOBAL_VARIABLE |
NodeType::NODE_FIELD |
NodeType::NODE_FUNCTION |
@@ -324,6 +333,8 @@ Tree<NodeType::BundleInfo> NodeType::getOverviewBundleTree() const
return Tree<BundleInfo>(BundleInfo(L"Classes"));
case NodeType::NODE_INTERFACE:
return Tree<BundleInfo>(BundleInfo(L"Interfaces"));
case NodeType::NODE_ANNOTATION:
return Tree<BundleInfo>(BundleInfo(L"Annotations"));
case NodeType::NODE_STRUCT:
return Tree<BundleInfo>(BundleInfo(L"Structs"));
case NodeType::NODE_FUNCTION:
@@ -355,6 +366,8 @@ FilePath NodeType::getIconPath() const
switch (m_type)
{
case NodeType::NODE_ANNOTATION:
return ResourcePaths::getGuiPath().concatenate(L"graph_view/images/annotation.png");
case NodeType::NODE_ENUM:
return ResourcePaths::getGuiPath().concatenate(L"graph_view/images/enum.png");
case NodeType::NODE_TYPEDEF:
@@ -376,6 +389,7 @@ bool NodeType::hasIcon() const
}
const NodeType::TypeMask mask =
NODE_ANNOTATION |
NodeType::NODE_ENUM |
NodeType::NODE_TYPEDEF |
NodeType::NODE_FILE |
@@ -397,6 +411,7 @@ NodeType::StyleType NodeType::getNodeStyle() const
case NodeType::NODE_CLASS:
case NodeType::NODE_UNION:
case NodeType::NODE_INTERFACE:
case NodeType::NODE_ANNOTATION:
case NodeType::NODE_ENUM:
case NodeType::NODE_TYPEDEF:
case NodeType::NODE_TEMPLATE_PARAMETER_TYPE:
+13 -13
View File
@@ -26,20 +26,20 @@ public:
NODE_STRUCT = 1 << 5,
NODE_CLASS = 1 << 6,
NODE_INTERFACE = 1 << 7,
NODE_GLOBAL_VARIABLE = 1 << 8,
NODE_FIELD = 1 << 9,
NODE_FUNCTION = 1 << 10,
NODE_METHOD = 1 << 11,
NODE_ANNOTATION = 1 << 8,
NODE_GLOBAL_VARIABLE = 1 << 9,
NODE_FIELD = 1 << 10,
NODE_FUNCTION = 1 << 11,
NODE_METHOD = 1 << 12,
NODE_ENUM = 1 << 13,
NODE_ENUM_CONSTANT = 1 << 14,
NODE_TYPEDEF = 1 << 15,
NODE_TEMPLATE_PARAMETER_TYPE = 1 << 16,
NODE_TYPE_PARAMETER = 1 << 17,
NODE_ENUM = 1 << 12,
NODE_ENUM_CONSTANT = 1 << 13,
NODE_TYPEDEF = 1 << 14,
NODE_TEMPLATE_PARAMETER_TYPE = 1 << 15,
NODE_TYPE_PARAMETER = 1 << 16,
NODE_FILE = 1 << 17,
NODE_MACRO = 1 << 18,
NODE_UNION = 1 << 19,
NODE_FILE = 1 << 18,
NODE_MACRO = 1 << 19,
NODE_UNION = 1 << 20,
NODE_MAX_VALUE = NODE_UNION
};
+4
View File
@@ -46,6 +46,8 @@ Edge::EdgeType Edge::intToType(int value)
return EDGE_AGGREGATION;
case EDGE_MACRO_USAGE:
return EDGE_MACRO_USAGE;
case EDGE_ANNOTATION_USAGE:
return EDGE_ANNOTATION_USAGE;
}
return EDGE_UNDEFINED;
@@ -159,6 +161,8 @@ std::wstring Edge::getReadableTypeString(EdgeType type)
return L"aggregation";
case EDGE_MACRO_USAGE:
return L"macro use";
case EDGE_ANNOTATION_USAGE:
return L"annotation use";
}
return L"";
+17 -16
View File
@@ -15,22 +15,23 @@ public:
typedef int TypeMask;
enum EdgeType : TypeMask
{
EDGE_UNDEFINED = 0x0,
EDGE_MEMBER = 0x1,
EDGE_TYPE_USAGE = 0x2,
EDGE_USAGE = 0x4,
EDGE_CALL = 0x8,
EDGE_INHERITANCE = 0x10,
EDGE_OVERRIDE = 0x20,
EDGE_TEMPLATE_ARGUMENT = 0x40,
EDGE_TYPE_ARGUMENT = 0x80,
EDGE_TEMPLATE_DEFAULT_ARGUMENT = 0x100,
EDGE_TEMPLATE_SPECIALIZATION = 0x200,
EDGE_TEMPLATE_MEMBER_SPECIALIZATION = 0x400,
EDGE_INCLUDE = 0x800,
EDGE_IMPORT = 0x1000,
EDGE_AGGREGATION = 0x2000,
EDGE_MACRO_USAGE = 0x4000
EDGE_UNDEFINED = 0,
EDGE_MEMBER = 1 << 0,
EDGE_TYPE_USAGE = 1 << 1,
EDGE_USAGE = 1 << 2,
EDGE_CALL = 1 << 3,
EDGE_INHERITANCE = 1 << 4,
EDGE_OVERRIDE = 1 << 5,
EDGE_TEMPLATE_ARGUMENT = 1 << 6,
EDGE_TYPE_ARGUMENT = 1 << 7,
EDGE_TEMPLATE_DEFAULT_ARGUMENT = 1 << 8,
EDGE_TEMPLATE_SPECIALIZATION = 1 << 9,
EDGE_TEMPLATE_MEMBER_SPECIALIZATION = 1 << 10,
EDGE_INCLUDE = 1 << 11,
EDGE_IMPORT = 1 << 12,
EDGE_AGGREGATION = 1 << 13,
EDGE_MACRO_USAGE = 1 << 14,
EDGE_ANNOTATION_USAGE = 1 << 15
};
static int typeToInt(EdgeType type);
+4
View File
@@ -109,6 +109,8 @@ NodeType ParserClientImpl::symbolKindToNodeType(SymbolKind symbolKind) const
{
switch (symbolKind)
{
case SYMBOL_ANNOTATION:
return NodeType::NODE_ANNOTATION;
case SYMBOL_BUILTIN_TYPE:
return NodeType::NODE_BUILTIN_TYPE;
case SYMBOL_CLASS:
@@ -179,6 +181,8 @@ Edge::EdgeType ParserClientImpl::referenceKindToEdgeType(ReferenceKind reference
return Edge::EDGE_IMPORT;
case REFERENCE_MACRO_USAGE:
return Edge::EDGE_MACRO_USAGE;
case REFERENCE_ANNOTATION_USAGE:
return Edge::EDGE_ANNOTATION_USAGE;
default:
break;
}
+2
View File
@@ -30,6 +30,8 @@ ReferenceKind intToReferenceKind(int v)
return REFERENCE_IMPORT;
case REFERENCE_MACRO_USAGE:
return REFERENCE_MACRO_USAGE;
case REFERENCE_ANNOTATION_USAGE:
return REFERENCE_ANNOTATION_USAGE;
}
return REFERENCE_UNDEFINED;
}
+2 -1
View File
@@ -16,7 +16,8 @@ enum ReferenceKind
REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION = 10,
REFERENCE_INCLUDE = 11,
REFERENCE_IMPORT = 12,
REFERENCE_MACRO_USAGE = 13
REFERENCE_MACRO_USAGE = 13,
REFERENCE_ANNOTATION_USAGE = 14
};
ReferenceKind intToReferenceKind(int v);
+2
View File
@@ -4,6 +4,8 @@ SymbolKind intToSymbolKind(int v)
{
switch (v)
{
case SYMBOL_ANNOTATION:
return SYMBOL_ANNOTATION;
case SYMBOL_BUILTIN_TYPE:
return SYMBOL_BUILTIN_TYPE;
case SYMBOL_CLASS:
+21 -20
View File
@@ -3,26 +3,27 @@
enum SymbolKind
{ // these values need to be the same as SymbolKind in Java code
SYMBOL_BUILTIN_TYPE = 1,
SYMBOL_CLASS = 2,
SYMBOL_ENUM = 3,
SYMBOL_ENUM_CONSTANT = 4,
SYMBOL_FIELD = 5,
SYMBOL_FUNCTION = 6,
SYMBOL_GLOBAL_VARIABLE = 7,
SYMBOL_INTERFACE = 8,
SYMBOL_LOCAL_VARIABLE = 9,
SYMBOL_MACRO = 10,
SYMBOL_METHOD = 11,
SYMBOL_NAMESPACE = 12,
SYMBOL_PACKAGE = 13,
SYMBOL_PARAMETER = 14,
SYMBOL_STRUCT = 15,
SYMBOL_TEMPLATE_PARAMETER = 16,
SYMBOL_TYPEDEF = 17,
SYMBOL_TYPE_PARAMETER = 18,
SYMBOL_UNION = 19,
SYMBOL_KIND_MAX = 20
SYMBOL_ANNOTATION = 1,
SYMBOL_BUILTIN_TYPE = 2,
SYMBOL_CLASS = 3,
SYMBOL_ENUM = 4,
SYMBOL_ENUM_CONSTANT = 5,
SYMBOL_FIELD = 6,
SYMBOL_FUNCTION = 7,
SYMBOL_GLOBAL_VARIABLE = 8,
SYMBOL_INTERFACE = 9,
SYMBOL_LOCAL_VARIABLE = 10,
SYMBOL_MACRO = 11,
SYMBOL_METHOD = 12,
SYMBOL_NAMESPACE = 13,
SYMBOL_PACKAGE = 14,
SYMBOL_PARAMETER = 15,
SYMBOL_STRUCT = 16,
SYMBOL_TEMPLATE_PARAMETER = 17,
SYMBOL_TYPEDEF = 18,
SYMBOL_TYPE_PARAMETER = 19,
SYMBOL_UNION = 20,
SYMBOL_KIND_MAX = 21
};
SymbolKind intToSymbolKind(int v);
@@ -30,7 +30,7 @@ namespace
}
}
const size_t SqliteIndexStorage::s_storageVersion = 18;
const size_t SqliteIndexStorage::s_storageVersion = 19;
SqliteIndexStorage::SqliteIndexStorage(const FilePath& dbFilePath)
: SqliteStorage(dbFilePath.getCanonical())
+104
View File
@@ -53,6 +53,33 @@ public:
));
}
void test_java_parser_finds_anotation_declaration_in_defaut_package()
{
std::shared_ptr<TestParserClient> client = parseCode(
"public @interface SampleAnnotation\n"
"{\n"
"}\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->annotations, L"public SampleAnnotation <1:1 <1:19 1:34> 3:1>"
));
}
void test_java_parser_finds_anotation_member_declaration()
{
std::shared_ptr<TestParserClient> client = parseCode(
"public @interface SampleAnnotation\n"
"{\n"
" public int value() default 0;\n"
"}\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->fields, L"public int SampleAnnotation.value <3:13 3:17>"
));
}
void test_java_parser_finds_class_declaration_in_defaut_package()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -781,6 +808,83 @@ public:
///////////////////////////////////////////////////////////////////////////////
// test finding usages of symbols
void test_java_parser_finds_usage_of_marker_annotation()
{
std::shared_ptr<TestParserClient> client = parseCode(
"public @interface SampleAnnotation\n"
"{\n"
"}\n"
"\n"
"@SampleAnnotation\n"
"class Foo\n"
"{\n"
"}\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->annotationUses, L"Foo -> SampleAnnotation <5:2 5:17>"
));
}
void test_java_parser_finds_usage_of_single_member_annotation()
{
std::shared_ptr<TestParserClient> client = parseCode(
"public @interface SampleAnnotation\n"
"{\n"
" public int value() default 0;\n"
"}\n"
"\n"
"@SampleAnnotation(33)\n"
"class Foo\n"
"{\n"
"}\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->annotationUses, L"Foo -> SampleAnnotation <6:2 6:17>"
));
}
void test_java_parser_finds_usage_of_normal_annotation()
{
std::shared_ptr<TestParserClient> client = parseCode(
"public @interface SampleAnnotation\n"
"{\n"
" public int a() default 0;\n"
" public int b() default 0;\n"
"}\n"
"\n"
"@SampleAnnotation()\n"
"class Foo\n"
"{\n"
"}\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->annotationUses, L"Foo -> SampleAnnotation <7:2 7:17>"
));
}
void test_java_parser_finds_usage_of_normal_annotation_member_in_initialization()
{
std::shared_ptr<TestParserClient> client = parseCode(
"public @interface SampleAnnotation\n"
"{\n"
" public int a() default 0;\n"
" public int b() default 0;\n"
"}\n"
"\n"
"@SampleAnnotation(a = 9)\n"
"class Foo\n"
"{\n"
"}\n"
);
TS_ASSERT(utility::containsElement<std::wstring>(
client->usages, L"Foo -> int SampleAnnotation.a <7:19 7:19>"
));
}
void test_java_parser_finds_inheritance_using_extends_keyword()
{
std::shared_ptr<TestParserClient> client = parseCode(
+2
View File
@@ -194,6 +194,8 @@ private:
return L"REFERENCE_IMPORT";
case REFERENCE_MACRO_USAGE:
return L"REFERENCE_MACRO_USAGE";
case REFERENCE_ANNOTATION_USAGE:
return L"REFERENCE_ANNOTATION_USAGE";
default:
break;
}
+7
View File
@@ -104,6 +104,9 @@ public:
case REFERENCE_MACRO_USAGE:
referenceContainer = &macroUses;
break;
case REFERENCE_ANNOTATION_USAGE:
referenceContainer = &annotationUses;
break;
default:
break;
}
@@ -145,6 +148,7 @@ public:
std::vector<std::wstring> classes;
std::vector<std::wstring> unions;
std::vector<std::wstring> interfaces;
std::vector<std::wstring> annotations;
std::vector<std::wstring> enums;
std::vector<std::wstring> enumConstants;
std::vector<std::wstring> functions;
@@ -166,6 +170,7 @@ public:
std::vector<std::wstring> usages; // for variables
std::vector<std::wstring> typeUses; // for types
std::vector<std::wstring> macroUses;
std::vector<std::wstring> annotationUses;
std::vector<std::wstring> templateArgumentTypes;
std::vector<std::wstring> typeArguments;
std::vector<std::wstring> templateDefaultArgumentTypes;
@@ -204,6 +209,8 @@ private:
return &unions;
case SYMBOL_INTERFACE:
return &interfaces;
case SYMBOL_ANNOTATION:
return &annotations;
case SYMBOL_ENUM:
return &enums;
case SYMBOL_ENUM_CONSTANT: