* @file
*
* MockManager is the global manager to generate the mocked version of a class or interface
* which is passed to createMock/createSpy calls.
*/
#ifndef CANGJIE_SEMA_MOCK_MANAGER_H
#define CANGJIE_SEMA_MOCK_MANAGER_H
#include "cangjie/Sema/TypeManager.h"
#include "cangjie/Modules/ImportManager.h"
#include "MockUtils.h"
namespace Cangjie {
enum class MockKind : uint8_t;
class MockManager {
public:
explicit MockManager(ImportManager& importManager, TypeManager& typeManager, const Ptr<MockUtils> mockUtils);
void LoadMockLibDecls();
struct GeneratedClassResult {
Ptr<AST::ClassDecl> classDecl;
bool generated;
};
GeneratedClassResult GenerateMockClassIfNeededAndGet(
AST::ClassLikeDecl& originalDecl, AST::Package& curPkg, MockKind mockKind);
void HandleMockAnnotatedLambdaValue(AST::Expr& expr);
void WrapWithRequireMockObject(AST::Expr& receiverExpr);
static OwnedPtr<AST::ThrowExpr> CreateIllegalMockCallException(
AST::File& curFile, TypeManager& typeMgr, ImportManager& importMgr);
static OwnedPtr<AST::CallExpr> CreateInitCallOfMockClass(
AST::ClassDecl& mockClass, std::vector<OwnedPtr<AST::FuncArg>>& mockCallArgs,
TypeManager& typeManager, const std::vector<Ptr<AST::Ty>> instTys,
const std::vector<Ptr<AST::Ty>> valueParamTys);
static bool IsMockCall(const AST::CallExpr& ce);
static bool IsMockClass(const AST::Decl& decl);
static MockKind GetMockKind(const AST::CallExpr& ce);
static Ptr<AST::ClassDecl> FindMockedClassOf(const AST::ClassLikeDecl& decl);
private:
static OwnedPtr<AST::VarDecl> CreateFieldDecl(
AST::ClassLikeDecl& decl, const std::string& identifier, const Ptr<AST::Ty> ty, const AST::Package& curPkg
);
TypeManager& typeManager;
ImportManager& importManager;
Ptr<MockUtils> mockUtils;
std::unordered_map<Ptr<AST::ClassLikeDecl>, Ptr<AST::ClassDecl>> mockedClassDecls;
std::unordered_map<Ptr<AST::ClassLikeDecl>, int> instantiationCounters;
std::unordered_map<Ptr<const AST::FuncDecl>, bool> defaultForTypePresence;
Ptr<AST::InterfaceDecl> callHandlerDecl;
Ptr<AST::InterfaceDecl> mockedInterfaceDecl;
Ptr<AST::StructDecl> parameterInfoDecl;
Ptr<AST::StructDecl> declIdDecl;
Ptr<AST::StructDecl> funcInfoDecl;
Ptr<AST::StructDecl> callDecl;
Ptr<AST::EnumDecl> onCallEnumDecl;
Ptr<AST::EnumDecl> declKindEnumDecl;
Ptr<AST::InterfaceDecl> hasDefaultValueForStubDecl;
Ptr<AST::ClassDecl> noDefaultValueForMockException;
Ptr<AST::ClassDecl> mockReturnValueTypeMismatchException;
Ptr<AST::FuncDecl> requireMockObject;
Ptr<AST::StructDecl> mockZeroValueDecl;
int ComputeInstantiationNumberToMangleMockedDecl(const AST::ClassLikeDecl& declToMock);
void FindOverridesInSuperDecl(
AST::ClassLikeDecl& superDecl, const AST::Decl& member, std::set<Ptr<AST::Decl>>& foundOverrides
) const;
void AddObjectSuperTypeIfNeeded(
const AST::ClassLikeDecl& originalDecl, AST::ClassDecl& mockedDecl
) const;
void AddMockedMembers(AST::ClassLikeDecl& originalDecl, AST::ClassDecl& mockedDecl,
std::vector<TypeSubst>& classGenericSubsts);
void AddMockedInterface(AST::ClassDecl& mockedDecl, AST::VarDecl& handlerFieldDecl);
OwnedPtr<AST::MatchExpr> CreateTypeCastForOnCallReturnValue(
OwnedPtr<AST::Expr> exprToCast, const Ptr<AST::Ty> castTy
) const;
OwnedPtr<AST::AssignExpr> CreateMemberAssignment(
AST::VarDecl& member, OwnedPtr<AST::Expr> rhsExpr
) const;
OwnedPtr<AST::MatchCase> CreateOnCallReturnZeroMatchCase(
const AST::FuncDecl& originalFunc, const Ptr<AST::Ty> zeroValueTy, AST::Decl& enumConstructor) const;
OwnedPtr<AST::MatchCase> CreateOnCallReturnMatchCase(
const AST::FuncDecl& originalFunc, const Ptr<AST::Ty> retTy, AST::Decl& enumConstructor) const;
OwnedPtr<AST::MatchCase> CreateOnCallThrowMatchCase(
const AST::FuncDecl& originalFunc, AST::Decl& enumConstructor) const;
OwnedPtr<AST::MatchCase> CreateOnCallCallBaseMatchCase(
AST::FuncDecl& originalFunc, const AST::FuncDecl& mockedFunc, AST::Decl& enumConstructor) const;
OwnedPtr<AST::MatchCase> CreateOnCallReturnDefaultMatchCase(
const AST::FuncDecl& originalFunc, const Ptr<AST::Ty> retTy, AST::Decl& enumConstructor);
Ptr<AST::FuncDecl> FindDefaultValueForStubMethod(const Ptr<AST::Ty> retTy) const;
OwnedPtr<AST::MatchCase> CreateOnCallResultMatchCase(
AST::FuncDecl& originalFunc, const Ptr<AST::FuncDecl> mockedFunc, AST::Decl& enumConstructor);
OwnedPtr<AST::FuncDecl> CreateEmptyConstructorDecl(
AST::ClassDecl& mockedClass, std::vector<OwnedPtr<AST::FuncParam>> params, AST::File& curFile) const;
OwnedPtr<AST::FuncDecl> CreateConstructorDecl(
AST::ClassDecl& mockedClass, std::set<std::string> membersToAssign, MockKind mockKind, AST::File& curFile
) const;
void AddAssignmentsForSuperFields(const AST::FuncDecl& constructorOfMockedDecl) const;
OwnedPtr<AST::CallExpr> CreateDeclId(const AST::Decl& decl, AST::File& curFile) const;
OwnedPtr<AST::CallExpr> CreateParamInfo(const AST::FuncParam& param, int position, AST::File& curFile
) const;
OwnedPtr<AST::ArrayLit> CreateParamsInfo(const AST::FuncDecl& decl, AST::File& curFile) const;
OwnedPtr<AST::ArrayLit> CreateTypeParamsInfo(const AST::FuncDecl& decl, AST::File& curFile) const;
OwnedPtr<AST::CallExpr> CreateFuncInfo(AST::FuncDecl& funcDecl, AST::File& curFile);
OwnedPtr<AST::Expr> CreateOuterDeclInfo(AST::FuncDecl& funcDecl, AST::File& curFile) const;
OwnedPtr<AST::CallExpr> CreateDeclKind(const AST::FuncDecl& decl) const;
OwnedPtr<AST::CallExpr> CreateCallInfo(
AST::FuncDecl& originalFunction, OwnedPtr<AST::Expr> mockedArgsArray, OwnedPtr<AST::Expr> typeArgsArray,
const Ptr<AST::File> curFile, OwnedPtr<AST::RefExpr> objRef
);
OwnedPtr<AST::CallExpr> CreateOnCallInvocation(
OwnedPtr<AST::Expr> mockedArgsArray, OwnedPtr<AST::Expr> typeArgsArray, AST::FuncDecl& originalFunc,
OwnedPtr<AST::RefExpr> objRef, OwnedPtr<AST::Expr> handler
);
OwnedPtr<AST::FuncDecl> CreateStaticMethodStub(
AST::FuncDecl& originalMethod, AST::ClassDecl& mockedDecl, std::vector<TypeSubst>& classGenericSubsts);
OwnedPtr<AST::FuncDecl> CreateMockedMethod(
AST::FuncDecl& originalMethod, AST::ClassDecl& mockedDecl, std::vector<TypeSubst>& classGenericSubsts);
OwnedPtr<AST::FuncDecl> CreateMockedMethodWithoutBody(
AST::FuncDecl& originalMethod, AST::ClassDecl& mockedDecl, std::vector<TypeSubst>& classGenericSubsts);
OwnedPtr<AST::PropDecl> CreateMockedProp(
AST::PropDecl& originalProp, AST::ClassDecl& mockedDecl, std::vector<TypeSubst>& classGenericSubsts);
void AddMockedMemberIfNeeded(
AST::ClassDecl& mockedDecl, AST::Decl& member, std::vector<TypeSubst>& classGenericSubsts);
OwnedPtr<AST::RefExpr> GetHandlerRefFromClass(const Ptr<AST::ClassDecl> decl);
void GenerateCallHandlerForStaticDecl(
AST::FuncDecl& decl, AST::Expr& injectTo, Ptr<AST::FuncDecl> declForInfo = nullptr);
void GenerateCallHandlerForMethodWithDefault(AST::CallExpr& callExpr);
void HandleMockAnnotatedLambdaWithCall(AST::CallExpr& callExpr);
void HandleMockAnnotatedLambdaWithMemberAccess(AST::MemberAccess& ma, AST::Expr& injectTo);
void HandleMockAnnotatedLambdaWithRefExpr(const AST::RefExpr& refExpr, AST::Expr& injectTo);
void HandleMockAnnotatedLambdaWithAssignExpr(AST::AssignExpr& assignExpr);
OwnedPtr<AST::Expr> GetCurrentStaticHandler(const Ptr<AST::File> curFile);
OwnedPtr<AST::Expr> GetMockedObjectHandler(OwnedPtr<AST::RefExpr> objRef, const Ptr<AST::File> curFile);
OwnedPtr<AST::LambdaExpr> GenerateCallHandlerLambda(
AST::FuncDecl& decl, const AST::Expr& injectTo, Ptr<AST::FuncDecl> declForInfo = nullptr);
std::vector<OwnedPtr<AST::MatchCase>> GenerateCallHandlerCases(
AST::FuncDecl& staticDecl, const AST::Expr& injectTo);
std::tuple<Ptr<AST::InterfaceDecl>, Ptr<AST::FuncDecl>> FindDefaultAccessorInterfaceAndFunction(
Ptr<AST::FuncDecl> original, Ptr<AST::MemberAccess> baseFunc);
};
}
#endif