private function findConstants($withDefined = false)
    {
        $constants        = array();
        $expressionSolver = new NodeExpressionResolver($this);

        // constants can be only top-level nodes in the namespace, so we can scan them directly
        foreach ($this->namespaceNode->stmts as $namespaceLevelNode) {
            if ($namespaceLevelNode instanceof Const_) {
                $nodeConstants = $namespaceLevelNode->consts;
                if (!empty($nodeConstants)) {
                    foreach ($nodeConstants as $nodeConstant) {
                        $expressionSolver->process($nodeConstant->value);
                        $constants[$nodeConstant->name->toString()] = $expressionSolver->getValue();
                    }
                }
            }
        }

        if ($withDefined) {
            foreach ($this->namespaceNode->stmts as $namespaceLevelNode) {
                if ($namespaceLevelNode instanceof Expression
                    && $namespaceLevelNode->expr instanceof FuncCall
                    && $namespaceLevelNode->expr->name instanceof Name
                    && (string)$namespaceLevelNode->expr->name === 'define'
                ) {
                    $functionCallNode = $namespaceLevelNode->expr;
                    $expressionSolver->process($functionCallNode->args[0]->value);
                    $constantName = $expressionSolver->getValue();

                    // Ignore constants, for which name can't be determined.
                    if (strlen($constantName)) {
                        $expressionSolver->process($functionCallNode->args[1]->value);
                        $constantValue = $expressionSolver->getValue();

                        $constants[$constantName] = $constantValue;
                    }
                }
            }
        }

        return $constants;
    }