Skip to content

Constructor support rebase #594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions integration-tests/cpp-example/cxx_lib/constructors.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include "constructors.h"
#include <cassert>

BigOrSmallInteger::BigOrSmallInteger(bool isBig) {
if (isBig) {
number = 10000;
} else {
number = 1;
}
}

BigOrSmallInteger::BigOrSmallInteger() {
number = 0;
}

TwoElements::TwoElements(int *first_, int *second_) {
if (*first_ > *second_) {
first = *first_;
second = *second_;
} else {
first = *second_;
second = *first_;
}
}

TwoElements::TwoElements() {
first = 0;
second = 0;
}

Closet::Closet(const Closet &other) {
length = other.length;
width = other.width;
height = other.height;
volume = other.volume;
}

Closet::Closet() {
length = 1.5;
width = 0.5;
height = 2.5;
volume = height * width * length;
}

Closet::Closet(double length_, double width_, double height_, double volume_) {
length = length_;
width = width_;
height = height_;
volume = volume_;
}

Closet2::Closet2() {
length = 1.5;
width = 0.5;
height = 2.5;
volume = height * width * length;
}

Closet3::Closet3(Closet3 &&other) {
length = other.length;
width = other.width;
height = other.height;
volume = other.volume;
}

Closet3::Closet3() {
length = 1.5;
width = 0.5;
height = 2.5;
volume = height * width * length;
}

Closet3::Closet3(double length_, double width_, double height_, double volume_) {
length = length_;
width = width_;
height = height_;
volume = volume_;
}

Closet4::Closet4(double length_, double width_, double height_) {
length = length_;
width = width_;
height = height_;
volume = height * width * length;
}

Closet4::Closet4() {
length = 1.5;
width = 0.5;
height = 2.5;
volume = height * width * length;
}
69 changes: 69 additions & 0 deletions integration-tests/cpp-example/cxx_lib/constructors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#ifndef UNITTESTBOT_CONSTRUCTORS_H
#define UNITTESTBOT_CONSTRUCTORS_H


struct BigOrSmallInteger {
int number;

BigOrSmallInteger();

BigOrSmallInteger(bool isBig);
};

struct TwoElements {
int first;
int second;

TwoElements();

TwoElements(int *first_, int *second_);
};

struct Closet {
double length;
double width;
double height;
double volume;

Closet();

Closet(double length_, double width_, double height_, double volume_);

Closet(const Closet &other);
};

struct Closet2 {
double length;
double width;
double height;
double volume;

Closet2();
};

struct Closet3 {
double length;
double width;
double height;
double volume;

Closet3();

Closet3(double length_, double width_, double height_, double volume_);

Closet3(Closet3 &&other);
};

struct Closet4 {
double length;
double width;
double height;
double volume;

Closet4();

Closet4(double length_, double width_, double height_);
};


#endif // UNITTESTBOT_CONSTRUCTORS_H
8 changes: 5 additions & 3 deletions server/src/BordersFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "clang-utils/Matchers.h"
#include "utils/CollectionUtils.h"
#include "utils/CompilationUtils.h"
#include "clang-utils/ClangUtils.h"

#include "loguru.h"

Expand Down Expand Up @@ -38,9 +39,8 @@ void BordersFinder::run(const MatchFinder::MatchResult &Result) {
lineInfo.initialized = true;
LOG_S(MAX) << "Class name: " << ST->getNameAsString();
LOG_S(MAX) << "Class's borders: " << lineInfo.begin << ' ' << lineInfo.end;
} else if (const auto *FS = Result.Nodes.getNodeAs<FunctionDecl>(Matchers::FUNCTION_DEF)) {
} else if (const FunctionDecl *FS = ClangUtils::getFunctionOrConstructor(Result)) {
SourceManager &sourceManager = Result.Context->getSourceManager();

fs::path path = sourceManager.getFileEntryForID(sourceManager.getMainFileID())
->tryGetRealPathName()
.str();
Expand Down Expand Up @@ -84,7 +84,7 @@ void BordersFinder::run(const MatchFinder::MatchResult &Result) {
lineInfo.scopeName = path.stem().string();
}
lineInfo.methodName = FS->getNameAsString();
const clang::QualType realReturnType = FS->getReturnType().getCanonicalType();
clang::QualType realReturnType = ClangUtils::getReturnType(FS, Result);
lineInfo.functionReturnType = ParamsHandler::getType(realReturnType, realReturnType, sourceManager);
lineInfo.initialized = true;

Expand Down Expand Up @@ -147,6 +147,8 @@ bool BordersFinder::containsLine(BordersFinder::Borders b) const {
void BordersFinder::findFunction() {
MatchFinder finder;
finder.addMatcher(Matchers::functionDefinitionMatcher, this);
finder.addMatcher(Matchers::constructorDefinitionMatcher, this);
finder.addMatcher(Matchers::memberConstructorDefinitionMatcher, this);
auto factory = clang::tooling::newFrontendActionFactory(&finder);
clangToolRunner.run(lineInfo.filePath, factory.get());
}
Expand Down
3 changes: 1 addition & 2 deletions server/src/Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,5 +1275,4 @@ bool Tests::MethodTestCase::isError() const {
bool Tests::TypeAndVarName::operator<(const Tests::TypeAndVarName &other) const {
return varName < other.varName || (varName == other.varName && type.mTypeName() < other.type.mTypeName());
}

}
} // tests
17 changes: 17 additions & 0 deletions server/src/Tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,12 @@ namespace tests {
bool isInline;
};

enum ConstructorInfo {
NOT_A_CONSTRUCTOR = 0,
CONSTRUCTOR = 1,
MOVE_CONSTRUCTOR = 2
};

struct MethodDescription {
std::optional<MethodParam> classObj;
std::string name;
Expand All @@ -508,6 +514,8 @@ namespace tests {
typedef std::unordered_map<std::string, std::vector<int>> SuiteNameToTestCasesMap;
SuiteNameToTestCasesMap suiteTestCases;

ConstructorInfo constructorInfo = ConstructorInfo::NOT_A_CONSTRUCTOR;

bool operator==(const MethodDescription &other) const;

MethodDescription();
Expand Down Expand Up @@ -571,6 +579,15 @@ namespace tests {
}
return std::nullopt;
}

[[nodiscard]] bool isConstructor() const {
return constructorInfo == Tests::ConstructorInfo::CONSTRUCTOR ||
constructorInfo == Tests::ConstructorInfo::MOVE_CONSTRUCTOR;
}

[[nodiscard]] bool isMoveConstructor() const {
return constructorInfo == Tests::ConstructorInfo::MOVE_CONSTRUCTOR;
}
};

struct MethodDescriptionToStringEqual {
Expand Down
21 changes: 21 additions & 0 deletions server/src/clang-utils/ClangUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,25 @@ namespace ClangUtils {
}
return false;
}

const clang::CXXConstructorDecl *getConstructor(const clang::ast_matchers::MatchFinder::MatchResult &Result) {
return Result.Nodes.getNodeAs<clang::CXXConstructorDecl>(Matchers::CONSTRUCTOR_DEF);
}

const clang::FunctionDecl *getFunctionOrConstructor(const clang::ast_matchers::MatchFinder::MatchResult &Result) {
const auto *FS = Result.Nodes.getNodeAs<clang::FunctionDecl>(Matchers::FUNCTION_DEF);
if (!FS) {
FS = getConstructor(Result);
}
return FS;
}


clang::QualType getReturnType(const clang::FunctionDecl *FS, const clang::ast_matchers::MatchFinder::MatchResult &Result) {
clang::QualType realReturnType = FS->getReturnType().getCanonicalType();
if (const auto *CS = getConstructor(Result)) {
realReturnType = CS->getThisObjectType();
}
return realReturnType;
}
}
4 changes: 4 additions & 0 deletions server/src/clang-utils/ClangUtils.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#ifndef UNITTESTBOT_CLANGUTILS_H
#define UNITTESTBOT_CLANGUTILS_H

#include "clang-utils/Matchers.h"
#include <clang/AST/Type.h>

namespace ClangUtils {
bool isIncomplete(clang::QualType type);
const clang::CXXConstructorDecl *getConstructor(const clang::ast_matchers::MatchFinder::MatchResult &Result);
const clang::FunctionDecl *getFunctionOrConstructor(const clang::ast_matchers::MatchFinder::MatchResult &Result);
clang::QualType getReturnType(const clang::FunctionDecl *FS, const clang::ast_matchers::MatchFinder::MatchResult &Result);
};


Expand Down
8 changes: 7 additions & 1 deletion server/src/clang-utils/Matchers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ namespace Matchers {
functionDecl(functionDefinitionTraits)
.bind(FUNCTION_DEF);

const DeclarationMatcher constructorDefinitionMatcher = cxxConstructorDecl(isDefinition()).bind(CONSTRUCTOR_DEF);

const DeclarationMatcher memberConstructorDefinitionMatcher = cxxRecordDecl(cxxConstructorDecl(isDefinition())).bind(CONSTRUCTOR_DEF);

const DeclarationMatcher anyTypeDeclarationMatcher =
anyOf(
structMatcher,
Expand Down Expand Up @@ -126,7 +130,9 @@ namespace Matchers {

const DeclarationMatcher anyToplevelDeclarationMatcher = anyOf(
anyToplevelTypeDeclarationMatcher,
functionDefinitionMatcher);
functionDefinitionMatcher,
constructorDefinitionMatcher,
memberConstructorDefinitionMatcher);

const DeclarationMatcher globalVariableUsageMatcher = functionDecl(functionDefinitionTraits,
forEachDescendant(declRefExpr(
Expand Down
3 changes: 3 additions & 0 deletions server/src/clang-utils/Matchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Matchers {
static inline const std::string TYPEDEF_UNION_DECL = "the_union_typedef";

static inline const std::string FUNCTION_DEF = "function_def";
static inline const std::string CONSTRUCTOR_DEF = "constructor_def";
static inline const std::string TOPLEVEL_TYPEDEF = "typedef_decl";

static inline const std::string TOPLEVEL_VAR_DECL = "toplevel_var_decl";
Expand All @@ -38,6 +39,8 @@ namespace Matchers {
static inline const std::string RETURN = "return";

extern const DeclarationMatcher functionDefinitionMatcher;
extern const DeclarationMatcher constructorDefinitionMatcher;
extern const DeclarationMatcher memberConstructorDefinitionMatcher;

extern const DeclarationMatcher structMatcher;
extern const DeclarationMatcher structJustDeclMatcher;
Expand Down
3 changes: 2 additions & 1 deletion server/src/clang-utils/SourceToHeaderMatchCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "SourceToHeaderRewriter.h"
#include "printers/Printer.h"
#include "utils/ExecUtils.h"
#include "clang-utils/ClangUtils.h"

#include "loguru.h"

Expand Down Expand Up @@ -80,7 +81,7 @@ void SourceToHeaderMatchCallback::checkTypedef(const MatchFinder::MatchResult &R

void SourceToHeaderMatchCallback::checkFunctionDecl(
const ast_matchers::MatchFinder::MatchResult &Result) {
if (const auto *decl = Result.Nodes.getNodeAs<FunctionDecl>(FUNCTION_DEF)) {
if (const FunctionDecl *decl = ClangUtils::getFunctionOrConstructor(Result)) {
if (decl->isInlined() && decl->getStorageClass() == SC_None) {
LOG_S(DEBUG)
<< "inline function without static or extern modifier is not supported by now";
Expand Down
6 changes: 6 additions & 0 deletions server/src/fetchers/Fetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Fetcher::Fetcher(Options options,
addMatcher<TypeDeclsMatchCallback>(structJustDeclMatcher);
}
if (options.has(Options::Value::FUNCTION)) {
addMatcher<FunctionDeclsMatchCallback>(constructorDefinitionMatcher, false, false, false);
addMatcher<FunctionDeclsMatchCallback>(memberConstructorDefinitionMatcher, false, false, false);
addMatcher<FunctionDeclsMatchCallback>(functionDefinitionMatcher, false, false, false);
}
if (options.has(Options::Value::GLOBAL_VARIABLE_USAGE)) {
Expand All @@ -50,11 +52,15 @@ Fetcher::Fetcher(Options options,
sourceFileCallbacks.add(std::move(callback));
}
if (options.has(Options::Value::FUNCTION_NAMES_ONLY)) {
addMatcher<FunctionDeclsMatchCallback>(constructorDefinitionMatcher, true, false, false);
addMatcher<FunctionDeclsMatchCallback>(memberConstructorDefinitionMatcher, true, false, false);
addMatcher<FunctionDeclsMatchCallback>(functionDefinitionMatcher, true, false, false);
auto callback = std::make_unique<SingleFileParseModeCallback>();
sourceFileCallbacks.add(std::move(callback));
}
if (options.has(Options::Value::RETURN_TYPE_NAMES_ONLY)) {
addMatcher<FunctionDeclsMatchCallback>(constructorDefinitionMatcher, false, true, true);
addMatcher<FunctionDeclsMatchCallback>(memberConstructorDefinitionMatcher, false, true, true);
addMatcher<FunctionDeclsMatchCallback>(functionDefinitionMatcher, false, true, true);
auto callback = std::make_unique<SingleFileParseModeCallback>();
sourceFileCallbacks.add(std::move(callback));
Expand Down
Loading