logic: fixed bug where anonymous symbols were only partly named like the enclosing typedef

* removed post processing for anonymous typedefs. The storage transformation did not work in
  cases where the typedef is recorded in a previously indexed header. No type information
  was recorded while indexing the header a second time. But this type information would have
  been required by the transformation.
This commit is contained in:
mlangkabel
2017-12-21 19:36:16 +01:00
parent 1a9d736f28
commit 455c1230b1
23 changed files with 167 additions and 380 deletions
-10
View File
@@ -24,16 +24,6 @@ Settings.cpp WARNING: File for Settings not found: data/SettingsTestSuite/wrong_
SourceLocationCollection.cpp ERROR: SourceLocation has wrong boundaries: file.c 2:3 2:1
SourceLocationCollection.cpp ERROR: SourceLocation has wrong boundaries: file.c 4:1 1:10
TextAccess.cpp ERROR: Could not open file path/to/test.h
StorageTransformationAnonymousTypedef.cpp INFO: Applying storage transformation to rename anonymous types inside typedefs.
StorageTransformationAnonymousTypedef.cpp INFO: Renamed 1 types.
StorageTransformationAnonymousTypedef.cpp INFO: Applying storage transformation to rename anonymous types inside typedefs.
StorageTransformationAnonymousTypedef.cpp INFO: Renamed 1 types.
StorageTransformationAnonymousTypedef.cpp INFO: Applying storage transformation to rename anonymous types inside typedefs.
StorageTransformationAnonymousTypedef.cpp INFO: Renamed 1 types.
StorageTransformationAnonymousTypedef.cpp INFO: Applying storage transformation to rename anonymous types inside typedefs.
StorageTransformationAnonymousTypedef.cpp INFO: Renamed 1 types.
StorageTransformationAnonymousTypedef.cpp INFO: Applying storage transformation to rename anonymous types inside typedefs.
StorageTransformationAnonymousTypedef.cpp INFO: Renamed 0 types.
TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
@@ -21,7 +21,6 @@ void SharedIndexerCommand::fromLocal(IndexerCommand* indexerCommand)
setCompilerFlags(cmd->getCompilerFlags());
setSystemHeaderSearchPaths(cmd->getSystemHeaderSearchPaths());
setFrameworkSearchhPaths(cmd->getFrameworkSearchPaths());
setShouldApplyAnonymousTypedefTransformation(cmd->shouldApplyAnonymousTypedefTransformation());
}
else if (dynamic_cast<IndexerCommandCxxManual*>(indexerCommand) != NULL)
{
@@ -32,7 +31,6 @@ void SharedIndexerCommand::fromLocal(IndexerCommand* indexerCommand)
setCompilerFlags(cmd->getCompilerFlags());
setSystemHeaderSearchPaths(cmd->getSystemHeaderSearchPaths());
setFrameworkSearchhPaths(cmd->getFrameworkSearchPaths());
setShouldApplyAnonymousTypedefTransformation(cmd->shouldApplyAnonymousTypedefTransformation());
}
else if (dynamic_cast<IndexerCommandJava*>(indexerCommand) != NULL)
{
@@ -61,8 +59,7 @@ std::shared_ptr<IndexerCommand> SharedIndexerCommand::fromShared(const SharedInd
indexerCommand.getWorkingDirectory(),
indexerCommand.getCompilerFlags(),
indexerCommand.getSystemHeaderSearchPaths(),
indexerCommand.getFrameworkSearchhPaths(),
indexerCommand.shouldApplyAnonymousTypedefTransformation()
indexerCommand.getFrameworkSearchhPaths()
);
return command;
}
@@ -75,8 +72,7 @@ std::shared_ptr<IndexerCommand> SharedIndexerCommand::fromShared(const SharedInd
indexerCommand.getLanguageStandard(),
indexerCommand.getSystemHeaderSearchPaths(),
indexerCommand.getFrameworkSearchhPaths(),
indexerCommand.getCompilerFlags(),
indexerCommand.shouldApplyAnonymousTypedefTransformation()
indexerCommand.getCompilerFlags()
);
return command;
}
@@ -274,16 +270,6 @@ void SharedIndexerCommand::setFrameworkSearchhPaths(const std::vector<FilePath>&
}
}
bool SharedIndexerCommand::shouldApplyAnonymousTypedefTransformation() const
{
return m_shouldApplyAnonymousTypedefTransformation;
}
void SharedIndexerCommand::setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation)
{
m_shouldApplyAnonymousTypedefTransformation = shouldApplyAnonymousTypedefTransformation;
}
std::vector<FilePath> SharedIndexerCommand::getClassPaths() const
{
std::vector<FilePath> result;
@@ -41,9 +41,6 @@ public:
std::vector<FilePath> getFrameworkSearchhPaths() const;
void setFrameworkSearchhPaths(const std::vector<FilePath>& searchPaths);
bool shouldApplyAnonymousTypedefTransformation() const;
void setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation);
std::vector<FilePath> getClassPaths() const;
void setClassPaths(const std::vector<FilePath>& classPaths);
@@ -72,7 +69,6 @@ private:
SharedMemory::Vector<SharedMemory::String> m_compilerFlags;
SharedMemory::Vector<SharedMemory::String> m_systemHeaderSearchPaths;
SharedMemory::Vector<SharedMemory::String> m_frameworkSearchPaths;
bool m_shouldApplyAnonymousTypedefTransformation;
// java
SharedMemory::Vector<SharedMemory::String> m_classPaths;
@@ -8,7 +8,6 @@ SourceGroupSettingsCxx::SourceGroupSettingsCxx(const std::string& id, SourceGrou
, m_headerSearchPaths(std::vector<FilePath>())
, m_frameworkSearchPaths(std::vector<FilePath>())
, m_compilerFlags(std::vector<std::string>())
, m_shouldApplyAnonymousTypedefTransformation(true)
{
}
@@ -25,7 +24,6 @@ void SourceGroupSettingsCxx::load(std::shared_ptr<const ConfigManager> config)
setHeaderSearchPaths(getPathValues(key + "/header_search_paths/header_search_path", config));
setFrameworkSearchPaths(getPathValues(key + "/framework_search_paths/framework_search_path", config));
setCompilerFlags(getValues<std::string>(key + "/compiler_flags/compiler_flag", std::vector<std::string>(), config));
setShouldApplyAnonymousTypedefTransformation(getValue<bool>(key + "/should_apply_anonymous_typedef_transformation", true, config));
}
void SourceGroupSettingsCxx::save(std::shared_ptr<ConfigManager> config)
@@ -37,7 +35,6 @@ void SourceGroupSettingsCxx::save(std::shared_ptr<ConfigManager> config)
setPathValues(key + "/header_search_paths/header_search_path", getHeaderSearchPaths(), config);
setPathValues(key + "/framework_search_paths/framework_search_path", getFrameworkSearchPaths(), config);
setValues(key + "/compiler_flags/compiler_flag", getCompilerFlags(), config);
setValue(key + "/should_apply_anonymous_typedef_transformation", getShouldApplyAnonymousTypedefTransformation(), config);
}
bool SourceGroupSettingsCxx::equals(std::shared_ptr<SourceGroupSettings> other) const
@@ -146,16 +143,6 @@ void SourceGroupSettingsCxx::setCompilerFlags(const std::vector<std::string>& co
m_compilerFlags = compilerFlags;
}
bool SourceGroupSettingsCxx::getShouldApplyAnonymousTypedefTransformation() const
{
return m_shouldApplyAnonymousTypedefTransformation;
}
void SourceGroupSettingsCxx::setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation)
{
m_shouldApplyAnonymousTypedefTransformation = shouldApplyAnonymousTypedefTransformation;
}
std::vector<std::string> SourceGroupSettingsCxx::getDefaultSourceExtensions() const
{
std::vector<std::string> defaultValues;
@@ -28,9 +28,6 @@ public:
std::vector<std::string> getCompilerFlags() const;
void setCompilerFlags(const std::vector<std::string>& compilerFlags);
bool getShouldApplyAnonymousTypedefTransformation() const;
void setShouldApplyAnonymousTypedefTransformation(bool shouldApplyAnonymousTypedefTransformation);
private:
virtual std::vector<std::string> getDefaultSourceExtensions() const;
virtual std::string getDefaultStandard() const;
@@ -38,7 +35,6 @@ private:
std::vector<FilePath> m_headerSearchPaths;
std::vector<FilePath> m_frameworkSearchPaths;
std::vector<std::string> m_compilerFlags;
bool m_shouldApplyAnonymousTypedefTransformation;
};
#endif // SOURCE_GROUP_SETTINGS_CXX_H
-3
View File
@@ -77,9 +77,6 @@ add_files(
data/parser/cxx/PreprocessorCallbacks.h
data/parser/cxx/utilityClang.cpp
data/parser/cxx/utilityClang.h
data/storage/StorageTransformationAnonymousTypedef.cpp
data/storage/StorageTransformationAnonymousTypedef.h
project/IncludeDirective.cpp
project/IncludeDirective.h
@@ -6,14 +6,12 @@ IndexerCommandCxx::IndexerCommandCxx(
const std::set<FilePath>& excludedPaths,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const std::vector<std::string>& compilerFlags,
const bool shouldApplyAnonymousTypedefTransformation
const std::vector<std::string>& compilerFlags
)
: IndexerCommand(sourceFilePath, indexedPaths, excludedPaths)
, m_systemHeaderSearchPaths(systemHeaderSearchPaths)
, m_frameworkSearchPaths(frameworkSearchPaths)
, m_compilerFlags(compilerFlags)
, m_shouldApplyAnonymousTypedefTransformation(shouldApplyAnonymousTypedefTransformation)
{
}
@@ -57,8 +55,3 @@ std::vector<std::string> IndexerCommandCxx::getCompilerFlags() const
{
return m_compilerFlags;
}
bool IndexerCommandCxx::shouldApplyAnonymousTypedefTransformation() const
{
return m_shouldApplyAnonymousTypedefTransformation;
}
+1 -5
View File
@@ -18,8 +18,7 @@ public:
const std::set<FilePath>& excludedPaths,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const std::vector<std::string>& compilerFlags,
const bool shouldApplyAnonymousTypedefTransformation);
const std::vector<std::string>& compilerFlags);
virtual ~IndexerCommandCxx();
virtual size_t getByteSize(size_t stringSize) const override;
@@ -28,13 +27,10 @@ public:
std::vector<FilePath> getFrameworkSearchPaths() const;
std::vector<std::string> getCompilerFlags() const;
bool shouldApplyAnonymousTypedefTransformation() const;
private:
std::vector<FilePath> m_systemHeaderSearchPaths;
std::vector<FilePath> m_frameworkSearchPaths;
std::vector<std::string> m_compilerFlags;
bool m_shouldApplyAnonymousTypedefTransformation;
};
#endif // INDEXER_COMMAND_CXXL_H
@@ -46,10 +46,9 @@ IndexerCommandCxxCdb::IndexerCommandCxxCdb(
const FilePath& workingDirectory,
const std::vector<std::string>& compilerFlags,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const bool shouldApplyAnonymousTypedefTransformation
const std::vector<FilePath>& frameworkSearchPaths
)
: IndexerCommandCxx(sourceFilePath, indexedPaths, excludedPaths, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags, shouldApplyAnonymousTypedefTransformation)
: IndexerCommandCxx(sourceFilePath, indexedPaths, excludedPaths, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags)
, m_workingDirectory(workingDirectory)
{
}
@@ -27,8 +27,7 @@ public:
const FilePath& workingDirectory,
const std::vector<std::string>& compilerFlags,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const bool shouldApplyAnonymousTypedefTransformation);
const std::vector<FilePath>& frameworkSearchPaths);
virtual ~IndexerCommandCxxCdb();
@@ -12,10 +12,9 @@ IndexerCommandCxxManual::IndexerCommandCxxManual(
const std::string& languageStandard,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const std::vector<std::string>& compilerFlags,
const bool shouldApplyAnonymousTypedefTransformation
const std::vector<std::string>& compilerFlags
)
: IndexerCommandCxx(sourceFilePath, indexedPaths, excludedPaths, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags, shouldApplyAnonymousTypedefTransformation)
: IndexerCommandCxx(sourceFilePath, indexedPaths, excludedPaths, systemHeaderSearchPaths, frameworkSearchPaths, compilerFlags)
, m_languageStandard(languageStandard)
{
}
@@ -18,8 +18,7 @@ public:
const std::string& languageStandard,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const std::vector<std::string>& compilerFlags,
const bool shouldApplyAnonymousTypedefTransformation);
const std::vector<std::string>& compilerFlags);
virtual ~IndexerCommandCxxManual();
-6
View File
@@ -5,7 +5,6 @@
#include "data/indexer/Indexer.h"
#include "data/parser/ParserClientImpl.h"
#include "data/storage/StorageTransformationAnonymousTypedef.h"
#include "utility/file/FileRegister.h"
template <typename IndexerCommandType, typename ParserType>
@@ -55,11 +54,6 @@ std::shared_ptr<IntermediateStorage> IndexerCxx<IndexerCommandType, ParserType>:
return std::shared_ptr<IntermediateStorage>();
}
if (indexerCommand->shouldApplyAnonymousTypedefTransformation())
{
StorageTransformationAnonymousTypedef::transform(storage);
}
return storage;
}
@@ -194,7 +194,6 @@ void CxxAstVisitorComponentIndexer::visitTagDecl(clang::TagDecl* d)
symbolKind
);
}
}
}
@@ -441,7 +440,7 @@ void CxxAstVisitorComponentIndexer::visitTypedefDecl(clang::TypedefDecl* d)
{
m_client->recordSymbol(
getAstVisitor()->getDeclNameCache()->getValue(d),
SYMBOL_TYPEDEF,
d->getAnonDeclWithTypedefName() == NULL ? SYMBOL_TYPEDEF : utility::convertTagKind(d->getAnonDeclWithTypedefName()->getTagKind()),
getParseLocation(d->getLocation()),
utility::convertAccessSpecifier(d->getAccess()),
utility::isImplicit(d) ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT
@@ -455,7 +454,7 @@ void CxxAstVisitorComponentIndexer::visitTypeAliasDecl(clang::TypeAliasDecl* d)
{
m_client->recordSymbol(
getAstVisitor()->getDeclNameCache()->getValue(d),
SYMBOL_TYPEDEF,
d->getAnonDeclWithTypedefName() == NULL ? SYMBOL_TYPEDEF : utility::convertTagKind(d->getAnonDeclWithTypedefName()->getTagKind()),
getParseLocation(d->getLocation()),
utility::convertAccessSpecifier(d->getAccess()),
utility::isImplicit(d) ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT
@@ -171,6 +171,14 @@ std::shared_ptr<CxxDeclName> CxxDeclNameResolver::getDeclName(const clang::Named
ScopedSwitcher<const clang::NamedDecl*> switcher(m_currentDecl, declaration);
std::string declNameString = declaration->getNameAsString();
if (const clang::TagDecl* tagDecl = clang::dyn_cast_or_null<clang::TagDecl>(declaration))
{
if (const clang::TypedefNameDecl* typedefNameDecl = tagDecl->getTypedefNameForAnonDecl())
{
declNameString = typedefNameDecl->getNameAsString();
}
}
if (const clang::TypeAliasDecl* typeAliasDecl = clang::dyn_cast_or_null<clang::TypeAliasDecl>(declaration))
{
clang::TypeAliasTemplateDecl* templatedDeclaration = typeAliasDecl->getDescribedAliasTemplate();
@@ -1,112 +0,0 @@
#include "data/storage/StorageTransformationAnonymousTypedef.h"
#include <map>
#include "data/graph/Node.h"
#include "data/name/NameDelimiterType.h"
#include "data/storage/IntermediateStorage.h"
#include "utility/logging/logging.h"
#include "utility/utilityString.h"
void StorageTransformationAnonymousTypedef::transform(std::shared_ptr<IntermediateStorage> storage)
{
LOG_INFO("Applying storage transformation to rename anonymous types inside typedefs.");
if (!storage)
{
return;
}
std::vector<StorageNode> nodes = storage->getStorageNodes();
std::vector<StorageEdge> edges = storage->getStorageEdges();
std::vector<StorageOccurrence> occurrences = storage->getStorageOccurrences();
std::map<Id, Id> nodesToMerge;
std::map<std::string, std::string> nodesToRename;
{
std::map<Id, StorageNode> typedefNodes;
std::map<Id, StorageNode> anonymousTypeNodes;
for (const StorageNode& node : nodes)
{
const NodeType::Type nodeType = utility::intToType(node.type);
if (nodeType & NodeType::NODE_TYPEDEF)
{
typedefNodes.insert(std::pair<Id, StorageNode>(node.id, node));
}
else if(nodeType & (NodeType::NODE_STRUCT | NodeType::NODE_CLASS | NodeType::NODE_ENUM | NodeType::NODE_UNION))
{
const NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName);
if (nameHierarchy.back() && utility::isPrefix("anonymous ", nameHierarchy.back()->getName()))
{
anonymousTypeNodes.insert(std::pair<Id, StorageNode>(node.id, node));
}
}
}
for (const StorageEdge& edge : edges)
{
if (Edge::intToType(edge.type) & Edge::EDGE_TYPE_USAGE)
{
std::map<Id, StorageNode>::const_iterator itAnonymousTypeNodes = anonymousTypeNodes.find(edge.targetNodeId);
if (itAnonymousTypeNodes != anonymousTypeNodes.end())
{
std::map<Id, StorageNode>::const_iterator itTypedefNodes = typedefNodes.find(edge.sourceNodeId);
if (itTypedefNodes != typedefNodes.end())
{
nodesToMerge.insert(std::pair<Id, Id>(itTypedefNodes->first, itAnonymousTypeNodes->first));
nodesToRename.insert(std::pair<std::string, std::string>(itAnonymousTypeNodes->second.serializedName, itTypedefNodes->second.serializedName));
}
}
}
}
}
// remove typedef nodes that refer to anonymous types
// and rename anonymous types to typedef name
for (size_t i = 0; i < nodes.size(); i++)
{
if (nodesToMerge.find(nodes[i].id) != nodesToMerge.end())
{
nodes.erase(nodes.begin() + i);
i--;
}
else
{
for (std::map<std::string, std::string>::const_iterator it = nodesToRename.begin(); it != nodesToRename.end(); it++)
{
if (utility::isPrefix(it->first, nodes[i].serializedName))
{
nodes[i].serializedName = it->second + nodes[i].serializedName.substr(it->first.size());
}
}
}
}
// redirect edges that pointed to removed nodes
for (StorageEdge& edge : edges)
{
std::map<Id, Id>::const_iterator it = nodesToMerge.find(edge.targetNodeId);
if (it != nodesToMerge.end())
{
edge.targetNodeId = it->second;
}
}
// relink source locations of removed nodes
for (StorageOccurrence& occurrence : occurrences)
{
std::map<Id, Id>::const_iterator it = nodesToMerge.find(occurrence.elementId);
if (it != nodesToMerge.end())
{
occurrence.elementId = it->second;
}
}
storage->setStorageNodes(nodes);
storage->setStorageEdges(edges);
storage->setStorageOccurrences(occurrences);
LOG_INFO("Renamed " + std::to_string(nodesToRename.size()) + " types.");
}
@@ -1,14 +0,0 @@
#ifndef STORAGE_TRANSFORMATION_ANONYMOUS_TYPEDEF_H
#define STORAGE_TRANSFORMATION_ANONYMOUS_TYPEDEF_H
#include <memory>
class IntermediateStorage;
class StorageTransformationAnonymousTypedef
{
public:
static void transform(std::shared_ptr<IntermediateStorage> storage);
};
#endif // STORAGE_TRANSFORMATION_ANONYMOUS_TYPEDEF_H
+1 -2
View File
@@ -118,8 +118,7 @@ std::vector<std::shared_ptr<IndexerCommand>> SourceGroupCxxCdb::getIndexerComman
FilePath(command.Directory),
currentCompilerFlags,
systemHeaderSearchPaths,
frameworkSearchPaths,
m_settings->getShouldApplyAnonymousTypedefTransformation()
frameworkSearchPaths
));
}
}
+1 -2
View File
@@ -65,8 +65,7 @@ std::vector<std::shared_ptr<IndexerCommand>> SourceGroupCxxEmpty::getIndexerComm
m_settings->getStandard(),
systemHeaderSearchPaths,
frameworkSearchPaths,
compilerFlags,
m_settings->getShouldApplyAnonymousTypedefTransformation()
compilerFlags
));
}
}
-1
View File
@@ -31,7 +31,6 @@ add_files(
SqliteBookmarkStorageTestSuite.h
SqliteIndexStorageTestSuite.h
StorageTestSuite.h
StorageTransformationAnonymousTypedefTestSuite.h
TaskSchedulerTestSuite.h
TextAccessTestSuite.h
UtilityStringTestSuite.h
+1 -2
View File
@@ -139,8 +139,7 @@ private:
"c++1z",
utility::concat(std::vector<FilePath> { projectDataSrcRoot }, ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded()),
ApplicationSettings::getInstance()->getFrameworkSearchPathsExpanded(),
std::vector<std::string> { "--target=x86_64-pc-windows-msvc" },
true
std::vector<std::string> { "--target=x86_64-pc-windows-msvc" }
);
parser.buildIndex(command);
+144 -7
View File
@@ -314,7 +314,7 @@ public:
"typedef struct\n"
"{\n"
" int x;\n"
"} Foo;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
@@ -328,11 +328,11 @@ public:
"typedef struct\n"
"{\n"
" int x;\n"
"} Foo;\n"
"};\n"
"typedef struct\n"
"{\n"
" float x;\n"
"} Bar;\n"
"};\n"
);
TS_ASSERT_EQUALS(client->structs.size(), 2);
@@ -347,7 +347,7 @@ public:
"{\n"
" int i;\n"
" float f;\n"
"} Foo;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
@@ -355,6 +355,144 @@ public:
));
}
void test_cxx_parser_finds_name_of_anonymous_struct_declared_inside_typedef()
{
std::shared_ptr<TestParserClient> client = parseCode(
"typedef struct\n"
"{\n"
" int x;\n"
"} Foo;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->structs, "Foo <1:9 <1:9 1:14> 4:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->structs, "Foo <4:3 4:5>"
));
}
void test_cxx_parser_finds_name_of_anonymous_class_declared_inside_typedef()
{
std::shared_ptr<TestParserClient> client = parseCode(
"typedef class\n"
"{\n"
" int x;\n"
"} Foo;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->classes, "Foo <1:9 <1:9 1:13> 4:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->classes, "Foo <4:3 4:5>"
));
}
void test_cxx_parser_finds_name_of_anonymous_enum_declared_inside_typedef()
{
std::shared_ptr<TestParserClient> client = parseCode(
"typedef enum\n"
"{\n"
" CONSTANT_1;\n"
"} Foo;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->enums, "Foo <1:9 <1:9 1:12> 4:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->enums, "Foo <4:3 4:5>"
));
}
void test_cxx_parser_finds_name_of_anonymous_union_declared_inside_typedef()
{
std::shared_ptr<TestParserClient> client = parseCode(
"typedef union\n"
"{\n"
" int x;\n"
" float y;\n"
"} Foo;\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->unions, "Foo <1:9 <1:9 1:13> 5:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->unions, "Foo <5:3 5:5>"
));
}
void test_cxx_parser_finds_name_of_anonymous_struct_declared_inside_type_alias()
{
std::shared_ptr<TestParserClient> client = parseCode(
"using Foo = struct\n"
"{\n"
" int x;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->structs, "Foo <1:13 <1:13 1:18> 4:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->structs, "Foo <1:7 1:9>"
));
}
void test_cxx_parser_finds_name_of_anonymous_class_declared_inside_type_alias()
{
std::shared_ptr<TestParserClient> client = parseCode(
"using Foo = class\n"
"{\n"
" int x;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->classes, "Foo <1:13 <1:13 1:17> 4:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->classes, "Foo <1:7 1:9>"
));
}
void test_cxx_parser_finds_name_of_anonymous_enum_declared_inside_type_alias()
{
std::shared_ptr<TestParserClient> client = parseCode(
"using Foo = enum\n"
"{\n"
" CONSTANT_1;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->enums, "Foo <1:13 <1:13 1:16> 4:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->enums, "Foo <1:7 1:9>"
));
}
void test_cxx_parser_finds_name_of_anonymous_union_declared_inside_type_alias()
{
std::shared_ptr<TestParserClient> client = parseCode(
"using Foo = union\n"
"{\n"
" int x;\n"
" float y;\n"
"};\n"
);
TS_ASSERT(utility::containsElement<std::string>(
client->unions, "Foo <1:13 <1:13 1:17> 5:1>"
));
TS_ASSERT(utility::containsElement<std::string>(
client->unions, "Foo <1:7 1:9>"
));
}
void test_cxx_parser_finds_enum_defined_in_global_namespace()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -423,7 +561,7 @@ public:
void test_cxx_parser_finds_type_alias_in_class()
{
std::shared_ptr<TestParserClient> client = parseCode(
std::shared_ptr<TestParserClient> client = parseCode(
"class Foo\n"
"{\n"
" using Bar = Foo;\n"
@@ -3839,8 +3977,7 @@ public:
"c++1z",
std::vector<FilePath>(),
std::vector<FilePath>(),
std::vector<std::string>(),
false
std::vector<std::string>()
);
std::shared_ptr<TestParserClient> client = std::make_shared<TestParserClient>();
@@ -1,158 +0,0 @@
#include "cxxtest/TestSuite.h"
#include "data/storage/StorageTransformationAnonymousTypedef.h"
#include "data/storage/IntermediateStorage.h"
#include "data/graph/Node.h"
#include "utility/utility.h"
class StorageTransformationAnonymousTypedefTestSuite: public CxxTest::TestSuite
{
public:
void test_transformation_removes_anonymous_class_that_has_typedef()
{
std::shared_ptr<IntermediateStorage> storage = std::make_shared<IntermediateStorage>();
Id anonymousTypeId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_CLASS), NameHierarchy::serialize(NameHierarchy("anonymous class (input.cc<1:9>)", NAME_DELIMITER_CXX))));
Id typedefId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_TYPEDEF), NameHierarchy::serialize(NameHierarchy("ClassTypedef", NAME_DELIMITER_CXX))));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), typedefId, anonymousTypeId));
StorageTransformationAnonymousTypedef::transform(storage);
const std::vector<StorageNode> nodes = storage->getStorageNodes();
std::vector<std::string> nodeNames(nodes.size());
std::transform(nodes.begin(), nodes.end(), nodeNames.begin(), [](const StorageNode& node)
{
return NameHierarchy::deserialize(node.serializedName).getQualifiedNameWithSignature();
});
TS_ASSERT_EQUALS(1, nodeNames.size());
TS_ASSERT(utility::containsElement<std::string>(
nodeNames, "ClassTypedef"
));
}
void test_transformation_redirects_incoming_edges_to_renamed_anonymous_class()
{
std::shared_ptr<IntermediateStorage> storage = std::make_shared<IntermediateStorage>();
Id anonymousTypeId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_CLASS), NameHierarchy::serialize(NameHierarchy("anonymous class (input.cc<1:9>)", NAME_DELIMITER_CXX))));
Id typedefId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_TYPEDEF), NameHierarchy::serialize(NameHierarchy("ClassTypedef", NAME_DELIMITER_CXX))));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), typedefId, anonymousTypeId));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), 42, typedefId));
StorageTransformationAnonymousTypedef::transform(storage);
Id targetNodeId = 0;
for (const StorageEdge& edge : storage->getStorageEdges())
{
if (edge.sourceNodeId == 42)
{
targetNodeId = edge.targetNodeId;
break;
}
}
std::string targetNodeName = "";
for (const StorageNode& node : storage->getStorageNodes())
{
if (node.id == targetNodeId)
{
targetNodeName = NameHierarchy::deserialize(node.serializedName).getQualifiedNameWithSignature();
break;
}
}
TS_ASSERT_EQUALS(targetNodeName, "ClassTypedef");
}
void test_transformation_keeps_outgoing_edges_of_renamed_anonymous_class()
{
std::shared_ptr<IntermediateStorage> storage = std::make_shared<IntermediateStorage>();
Id anonymousTypeId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_CLASS), NameHierarchy::serialize(NameHierarchy("anonymous class (input.cc<1:9>)", NAME_DELIMITER_CXX))));
Id typedefId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_TYPEDEF), NameHierarchy::serialize(NameHierarchy("ClassTypedef", NAME_DELIMITER_CXX))));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), typedefId, anonymousTypeId));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), anonymousTypeId, 42));
StorageTransformationAnonymousTypedef::transform(storage);
Id sourceNodeId = 0;
for (const StorageEdge& edge : storage->getStorageEdges())
{
if (edge.targetNodeId == 42)
{
sourceNodeId = edge.sourceNodeId;
break;
}
}
std::string sourceNodeName = "";
for (const StorageNode& node : storage->getStorageNodes())
{
if (node.id == sourceNodeId)
{
sourceNodeName = NameHierarchy::deserialize(node.serializedName).getQualifiedNameWithSignature();
break;
}
}
TS_ASSERT_EQUALS(sourceNodeName, "ClassTypedef");
}
void test_transformation_renames_child_node_of_anonymous_class()
{
std::shared_ptr<IntermediateStorage> storage = std::make_shared<IntermediateStorage>();
Id anonymousTypeId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_CLASS), NameHierarchy::serialize(NameHierarchy("anonymous class (input.cc<1:9>)", NAME_DELIMITER_CXX))));
Id typedefId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_TYPEDEF), NameHierarchy::serialize(NameHierarchy("ClassTypedef", NAME_DELIMITER_CXX))));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), typedefId, anonymousTypeId));
Id anonymousTypeMemberId = storage->addNode(StorageNodeData(
utility::nodeTypeToInt(NodeType::NODE_FIELD),
NameHierarchy::serialize(NameHierarchy(utility::createVectorFromElements<std::string>("anonymous class (input.cc<1:9>)", "field"), NAME_DELIMITER_CXX))
));
StorageTransformationAnonymousTypedef::transform(storage);
std::string memberNodeName = "";
for (const StorageNode& node : storage->getStorageNodes())
{
if (node.id == anonymousTypeMemberId)
{
memberNodeName = NameHierarchy::deserialize(node.serializedName).getQualifiedNameWithSignature();
break;
}
}
TS_ASSERT_EQUALS(memberNodeName, "ClassTypedef::field");
}
void test_transformation_does_not_rename_named_class_with_typedef_in_anonymous_namespace()
{
std::shared_ptr<IntermediateStorage> storage = std::make_shared<IntermediateStorage>();
Id typeId = storage->addNode(StorageNodeData(
utility::nodeTypeToInt(NodeType::NODE_CLASS),
NameHierarchy::serialize(NameHierarchy(utility::createVectorFromElements<std::string>("anonymous namespace (input.cc<1:9>)", "Type"), NAME_DELIMITER_CXX))
));
Id typedefId = storage->addNode(StorageNodeData(utility::nodeTypeToInt(NodeType::NODE_TYPEDEF), NameHierarchy::serialize(NameHierarchy("ClassTypedef", NAME_DELIMITER_CXX))));
storage->addEdge(StorageEdgeData(Edge::typeToInt(Edge::EDGE_TYPE_USAGE), typedefId, typeId));
StorageTransformationAnonymousTypedef::transform(storage);
const std::vector<StorageNode> nodes = storage->getStorageNodes();
std::vector<std::string> nodeNames(nodes.size());
std::transform(nodes.begin(), nodes.end(), nodeNames.begin(), [](const StorageNode& node)
{
return NameHierarchy::deserialize(node.serializedName).getQualifiedNameWithSignature();
});
TS_ASSERT_EQUALS(2, nodeNames.size());
TS_ASSERT(utility::containsElement<std::string>(
nodeNames, "ClassTypedef"
));
TS_ASSERT(utility::containsElement<std::string>(
nodeNames, "anonymous namespace (input.cc<1:9>)::Type"
));
}
};