Ejemplo n.º 1
0
        public IReadOnlyList <IKernelCommand> SplitSubmission(SubmitCode submitCode)
        {
            var commands = new List <IKernelCommand>();
            var nugetRestoreOnKernels = new HashSet <string>();
            var hoistedCommandsIndex  = 0;

            var tree             = Parse(submitCode.Code, submitCode.TargetKernelName);
            var nodes            = tree.GetRoot().ChildNodes.ToArray();
            var targetKernelName = submitCode.TargetKernelName ?? KernelLanguage;

            foreach (var node in nodes)
            {
                switch (node)
                {
                case DirectiveNode directiveNode:
                    var parseResult = directiveNode.GetDirectiveParseResult();

                    if (parseResult.Errors.Any())
                    {
                        commands.Clear();
                        commands.Add(
                            new AnonymousKernelCommand((kernelCommand, context) =>
                        {
                            var message =
                                string.Join(Environment.NewLine,
                                            parseResult.Errors
                                            .Select(e => e.ToString()));

                            context.Fail(message: message);
                            return(Task.CompletedTask);
                        }, parent: submitCode.Parent));
                        break;
                    }

                    var directiveCommand = new DirectiveCommand(
                        parseResult,
                        submitCode.Parent,
                        directiveNode);

                    if (directiveNode is KernelNameDirectiveNode kernelNameNode)
                    {
                        targetKernelName = kernelNameNode.KernelName;
                    }

                    if (parseResult.CommandResult.Command.Name == "#r")
                    {
                        var value = parseResult.CommandResult.GetArgumentValueOrDefault <PackageReferenceOrFileInfo>("package");

                        if (value.Value is FileInfo)
                        {
                            AddHoistedCommand(
                                new SubmitCode(
                                    directiveNode,
                                    submitCode.SubmissionType,
                                    submitCode.Parent));
                        }
                        else
                        {
                            AddHoistedCommand(directiveCommand);
                            nugetRestoreOnKernels.Add(targetKernelName);
                        }
                    }
                    else if (parseResult.CommandResult.Command.Name == "#i")
                    {
                        directiveCommand.TargetKernelName = targetKernelName;
                        AddHoistedCommand(directiveCommand);
                    }
                    else
                    {
                        commands.Add(directiveCommand);
                    }

                    break;

                case LanguageNode languageNode:
                    commands.Add(new SubmitCode(
                                     languageNode,
                                     submitCode.SubmissionType,
                                     submitCode.Parent));
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(node));
                }
            }

            foreach (var kernelName in nugetRestoreOnKernels)
            {
                var findKernel = _kernel.FindKernel(kernelName);

                if (findKernel is KernelBase kernelBase &&
                    kernelBase.SubmissionParser.GetDirectiveParser() is {} parser)
                {
                    var restore = new DirectiveCommand(
                        parser.Parse("#!nuget-restore"),
                        submitCode.Parent);
                    AddHoistedCommand(restore);
                }
            }

            if (NoSplitWasNeeded(out var originalSubmission))
            {
                return(originalSubmission);
            }

            var parent = submitCode.Parent ?? submitCode;

            foreach (var command in commands.OfType <KernelCommandBase>())
            {
                command.Parent = parent;
            }

            return(commands);

            void AddHoistedCommand(IKernelCommand command)
            {
                commands.Insert(hoistedCommandsIndex++, command);
            }

            bool NoSplitWasNeeded(out IReadOnlyList <IKernelCommand> splitSubmission)
            {
                if (commands.Count == 0)
                {
                    splitSubmission = new[] { submitCode };
                    return(true);
                }

                if (commands.Count == 1)
                {
                    if (commands[0] is SubmitCode sc)
                    {
                        if (submitCode.Code.Equals(sc.Code, StringComparison.Ordinal))
                        {
                            splitSubmission = new[] { submitCode };
                            return(true);
                        }
                    }
                }

                splitSubmission = null;
                return(false);
            }
        }