protected function parseRawCommandLineArguments(array $rawCommandLineArguments, string $controllerObjectName, string $controllerCommandName): array
    {
        $commandLineArguments = [];
        $exceedingArguments = [];
        $commandMethodName = $controllerCommandName . 'Command';
        $commandMethodParameters = $this->commandManager->getCommandMethodParameters($controllerObjectName, $commandMethodName);

        $requiredArguments = [];
        $optionalArguments = [];
        foreach ($commandMethodParameters as $parameterName => $parameterInfo) {
            if ($parameterInfo['optional'] === false) {
                $requiredArguments[strtolower($parameterName)] = [
                    'parameterName' => $parameterName,
                    'type' => $parameterInfo['type']
                ];
            } else {
                $optionalArguments[strtolower($parameterName)] = [
                    'parameterName' => $parameterName,
                    'type' => $parameterInfo['type']
                ];
            }
        }

        $decidedToUseNamedArguments = false;
        $decidedToUseUnnamedArguments = false;
        while (count($rawCommandLineArguments) > 0) {
            $rawArgument = array_shift($rawCommandLineArguments);

            if ($rawArgument !== '' && $rawArgument[0] === '-') {
                if ($rawArgument[1] === '-') {
                    $rawArgument = substr($rawArgument, 2);
                } else {
                    $rawArgument = substr($rawArgument, 1);
                }
                $argumentName = $this->extractArgumentNameFromCommandLinePart($rawArgument);

                if (isset($optionalArguments[$argumentName])) {
                    $argumentValue = $this->getValueOfCurrentCommandLineOption($rawArgument, $rawCommandLineArguments, $optionalArguments[$argumentName]['type']);
                    $commandLineArguments[$optionalArguments[$argumentName]['parameterName']] = $argumentValue;
                } elseif (isset($requiredArguments[$argumentName])) {
                    if ($decidedToUseUnnamedArguments) {
                        throw new InvalidArgumentMixingException(sprintf('Unexpected named argument "%s". If you use unnamed arguments, all required arguments must be passed without a name.', $argumentName), 1309971821);
                    }
                    $decidedToUseNamedArguments = true;
                    $argumentValue = $this->getValueOfCurrentCommandLineOption($rawArgument, $rawCommandLineArguments, $requiredArguments[$argumentName]['type']);
                    $commandLineArguments[$requiredArguments[$argumentName]['parameterName']] = $argumentValue;
                    unset($requiredArguments[$argumentName]);
                }
            } else {
                if (count($requiredArguments) > 0) {
                    if ($decidedToUseNamedArguments) {
                        throw new InvalidArgumentMixingException(sprintf('Unexpected unnamed argument "%s". If you use named arguments, all required arguments must be passed named.', $rawArgument), 1309971820);
                    }
                    $argument = array_shift($requiredArguments);
                    $commandLineArguments[$argument['parameterName']] = $rawArgument;
                    $decidedToUseUnnamedArguments = true;
                } else {
                    $exceedingArguments[] = $rawArgument;
                }
            }
        }

        return [$commandLineArguments, $exceedingArguments];
    }