bool DeclarationAnalyzer::verifyProtocolFunction(const TypePtr& type, const TypePtr& protocol, const FunctionSymbolPtr& expected, bool supressError)
{
    std::vector<SymbolPtr> results;
    int filter = FilterLookupInExtension | FilterRecursive;
    if(expected->hasFlags(SymbolFlagStatic))
        filter |= FilterStaticMember;
    semanticAnalyzer->getMethodsFromType(type, expected->getName(), (MemberFilter)filter, results);
    TypePtr expectedType = expected->getType();
    assert(expectedType != nullptr);
    //verify if they're the same type
    bool found = false;
    for(const SymbolPtr& func : results)
    {
        if(checkTypeConform(type, expectedType, func->getType()))
        {
            found = true;
            break;
        }
    }
    if(!found)
    {
        if(!supressError)
        {
            error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), protocol->getName(), expected->getName());
        }
        return false;
    }
    return true;
}
void DeclarationAnalyzer::verifyProtocolFunction(const TypePtr& type, const TypePtr& protocol, const FunctionSymbolPtr& expected)
{
    SymbolPtr sym = type->getMember(expected->getName());
    TypePtr expectedType = expected->getType();
    assert(expectedType != nullptr);
    if(!sym)
    {
        error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), protocol->getName(), expected->getName());
        return;
    }
    else if(const FunctionSymbolPtr& func = std::dynamic_pointer_cast<FunctionSymbol>(sym))
    {
        //verify if they're the same type
        TypePtr funcType = func->getType();
        assert(funcType != nullptr);
        if(!Type::equals(funcType, expectedType))
        {
            error(type->getReference(),  Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), protocol->getName(), expected->getName());
        }
        return;
    }
    else if(FunctionOverloadedSymbolPtr funcs = std::dynamic_pointer_cast<FunctionOverloadedSymbol>(sym))
    {
        //verify if they're the same type
        bool found = false;
        for(const FunctionSymbolPtr& func : *funcs)
        {
            if(Type::equals(func->getType(), expectedType))
            {
                found = true;
                break;
            }
        }
        if(!found)
            error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), protocol->getName(), expected->getName());
        return;
    }
    else if(SymbolPlaceHolderPtr prop = std::dynamic_pointer_cast<SymbolPlaceHolder>(sym))
    {


    }
    error(type->getReference(), Errors::E_TYPE_DOES_NOT_CONFORM_TO_PROTOCOL_UNIMPLEMENTED_FUNCTION_3, type->getName(), protocol->getName(), expected->getName());
}
Example #3
0
void FunctionAnalyzer::visitFunction(const FunctionDefPtr& node)
{
    if(node->hasModifier(DeclarationModifiers::_Generated))
        return;
    //visit implementation
    FunctionSymbolPtr func = static_pointer_cast<SymboledFunction>(node)->symbol;
    if(func->getDeclaringType() && func->getDeclaringType()->getCategory() == Type::Protocol)
        return;//do not check implementation if it's defined as protocol function
    assert(func != nullptr);
    SCOPED_SET(ctx->currentFunction, func->getType());
    node->getBody()->accept(semanticAnalyzer);

    if(!Type::equals(func->getType()->getReturnType(), symbolRegistry->getGlobalScope()->Void()))
    {
        //check return in all branches
        ReturnStatementValidator validator(ctx);
        node->getBody()->accept(&validator);
        NodePtr refNode = validator.getRefNode() ? validator.getRefNode() : node;
        ReturnCoverResult  result = validator.getResult();
        if (result & ReturnCoverDeadcode)
        {
            this->warning(refNode, Errors::W_CODE_AFTER_A_WILL_NEVER_BE_EXECUTED_1, L"return");
            return;
        }
        switch (result)
        {
            case ReturnCoverNoResult:
            case ReturnCoverUnmatched:
            case ReturnCoverPartial:
                error(refNode, Errors::E_MISSING_RETURN_IN_A_FUNCTION_EXPECTED_TO_RETURN_A_1, func->getType()->getReturnType()->toString());
                return;
            default:
                break;
        }
    }
}
Example #4
0
void FunctionAnalyzer::visitInit(const InitializerDefPtr& node)
{
    FunctionSymbolPtr init = static_pointer_cast<SymboledInit>(node)->symbol;
    TypePtr funcType = init->getType();
    SCOPED_SET(ctx->currentFunction, funcType);
    {
        InitializationTracer tracer(nullptr, InitializationTracer::Sequence);
        SCOPED_SET(ctx->currentInitializationTracer, &tracer);
        node->getBody()->accept(semanticAnalyzer);
        //check if some stored property is not initialized
        for(const SymbolPtr& storedProp : ctx->currentType->getDeclaredStoredProperties())
        {
            if(!storedProp->hasFlags(SymbolFlagInitialized))
            {
                error(node, Errors::E_PROPERTY_A_NOT_INITIALIZED, L"self." + storedProp->getName());
                return;
            }
        }
    }

    if(node->hasModifier(DeclarationModifiers::Convenience))
    {
        //convenience initializer must call designated initializer in all paths
        InitializerValidator validator(ctx, this);
        node->getBody()->accept(&validator);
        NodePtr refNode = validator.getRefNode() ? validator.getRefNode() : node;
        if(validator.getResult() & InitializerCoverMultiple)
        {
            error(refNode, Errors::E_SELF_INIT_CALLED_MULTIPLE_TIMES_IN_INITIALIZER);
            return;
        }
        switch(validator.getResult())
        {
            case InitializerCoverNoResult:
            case InitializerCoverUnmatched:
            case InitializerCoverPartial:
                error(refNode, Errors::E_SELF_INIT_ISNT_CALLED_ON_ALL_PATHS_IN_DELEGATING_INITIALIZER);
                return;
            default:
                break;
        }

    }
    else
    {
        //designated initializer must call designated initializer if parent type has customized initializer
        bool hasCustomizedInitializer = false;
        if(ctx->currentType->getParentType())
        {
            FunctionOverloadedSymbolPtr inits = ctx->currentType->getDeclaredInitializer();
            if(inits)
            {
                for(const FunctionSymbolPtr& init : *inits)
                {
                    if(!init->getType()->getParameters().empty())
                    {
                        hasCustomizedInitializer = true;
                        break;
                    }
                }
            }
        }
        if(hasCustomizedInitializer)
        {
            InitializerValidator validator(ctx, this);
            node->getBody()->accept(&validator);
            NodePtr refNode = validator.getRefNode() ? validator.getRefNode() : node;
            if(validator.getResult() & InitializerCoverMultiple)
            {
                error(refNode, Errors::E_SUPER_INIT_CALLED_MULTIPLE_TIMES_IN_INITIALIZER);
                return;
            }
            switch(validator.getResult())
            {
                case InitializerCoverNoResult:
                case InitializerCoverUnmatched:
                case InitializerCoverPartial:
                    error(refNode, Errors::E_SUPER_INIT_ISNT_CALLED_BEFORE_RETURNING_FROM_INITIALIZER);
                    return;
                default:
                    break;
            }
        }

    }
}