public IReadOnlyList <IKernelCommand> SplitSubmission(SubmitCode submitCode) { var directiveParser = GetDirectiveParser(); var lines = new Queue <string>( submitCode.Code.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None)); var linesToForward = new List <string>(); var commands = new List <IKernelCommand>(); var packageCommands = new List <IKernelCommand>(); var commandWasSplit = false; while (lines.Count > 0) { var currentLine = lines.Dequeue(); if (currentLine.TrimStart().StartsWith("#")) { var parseResult = directiveParser.Parse(currentLine); var command = parseResult.CommandResult.Command; if (parseResult.Errors.Count == 0) { commandWasSplit = true; if (AccumulatedSubmission() is { } cmd) { commands.Add(cmd); } var runDirective = new DirectiveCommand(parseResult); if (command.Name == "#r" || command.Name == "#i") { packageCommands.Add(runDirective); } else { commands.Add(runDirective); } } else { if (command == parseResult.Parser.Configuration.RootCommand) { linesToForward.Add(currentLine); } else if (IsDirectiveSupportedByCompiler(command, parseResult)) { linesToForward.Add(currentLine); } else { 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); })); } } } else { linesToForward.Add(currentLine); } } if (commandWasSplit) { if (AccumulatedSubmission() is { } command) { commands.Add(command); } } else { commands.Add(submitCode); } if (packageCommands.Count > 0) { var parseResult = directiveParser.Parse("#!nuget-restore"); packageCommands.Add(new DirectiveCommand(parseResult)); } return(packageCommands.Concat(commands).ToArray()); IKernelCommand AccumulatedSubmission() { if (linesToForward.Any()) { var code = string.Join(Environment.NewLine, linesToForward); linesToForward.Clear(); if (!string.IsNullOrWhiteSpace(code)) { return(new SubmitCode(code)); } } return(null); } }
private IReadOnlyList <KernelCommand> SplitSubmission( KernelCommand originalCommand, string code, CreateChildCommand createCommand) { var commands = new List <KernelCommand>(); var nugetRestoreOnKernels = new HashSet <string>(); var hoistedCommandsIndex = 0; var tree = Parse(code, originalCommand.TargetKernelName); var nodes = tree.GetRoot().ChildNodes.ToArray(); var targetKernelName = originalCommand.TargetKernelName ?? KernelLanguage; var lastKernelUri = originalCommand.KernelUri; KernelNameDirectiveNode lastKernelNameNode = null; foreach (var node in nodes) { switch (node) { case DirectiveNode directiveNode: var parseResult = directiveNode.GetDirectiveParseResult(); if (parseResult.Errors.Any()) { if (directiveNode.IsUnknownActionDirective()) { commands.Add(createCommand(directiveNode, originalCommand, lastKernelNameNode)); } else { 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: originalCommand)); } break; } var directiveCommand = new DirectiveCommand( parseResult, originalCommand, directiveNode) { TargetKernelName = targetKernelName }; if (directiveNode is KernelNameDirectiveNode kernelNameNode) { targetKernelName = kernelNameNode.KernelName; lastKernelNameNode = kernelNameNode; } if (parseResult.CommandResult.Command.Name == "#r") { var value = parseResult.ValueForArgument <PackageReferenceOrFileInfo>("package"); if (value.Value is FileInfo) { AddHoistedCommand(createCommand(directiveNode, originalCommand, lastKernelNameNode)); } else { directiveCommand.KernelUri = lastKernelUri; directiveCommand.TargetKernelName = targetKernelName; AddHoistedCommand(directiveCommand); nugetRestoreOnKernels.Add(targetKernelName); } } else if (parseResult.CommandResult.Command.Name == "#i") { directiveCommand.KernelUri = lastKernelUri; directiveCommand.TargetKernelName = targetKernelName; AddHoistedCommand(directiveCommand); } else { commands.Add(directiveCommand); if (directiveNode is KernelNameDirectiveNode) { hoistedCommandsIndex = commands.Count; } } break; case LanguageNode languageNode: commands.Add(createCommand(languageNode, originalCommand, lastKernelNameNode)); break; default: throw new ArgumentOutOfRangeException(nameof(node)); } } foreach (var kernelName in nugetRestoreOnKernels) { var kernel = _kernel.FindKernel(kernelName); if (kernel?.SubmissionParser.GetDirectiveParser() is { } parser) { var restore = new DirectiveCommand( parser.Parse("#!nuget-restore"), originalCommand) { KernelUri = kernel.Uri, TargetKernelName = kernelName }; AddHoistedCommand(restore); } } if (NoSplitWasNeeded(out var originalSubmission)) { return(originalSubmission); } foreach (var command in commands) { command.Parent = originalCommand; } return(commands); void AddHoistedCommand(KernelCommand command) { commands.Insert(hoistedCommandsIndex++, command); } bool NoSplitWasNeeded(out IReadOnlyList <KernelCommand> splitSubmission) { if (commands.Count == 0) { splitSubmission = new[] { originalCommand }; return(true); } if (commands.Count == 1) { if (commands[0] is SubmitCode sc) { if (code.Equals(sc.Code, StringComparison.Ordinal)) { splitSubmission = new[] { originalCommand }; return(true); } } } splitSubmission = null; return(false); } }
public IReadOnlyList <IKernelCommand> SplitSubmission(SubmitCode submitCode) { var commands = new List <IKernelCommand>(); var nugetRestoreOnKernels = new HashSet <string>(); var hoistedCommandsIndex = 0; var tree = Parse(submitCode.Code); var nodes = tree.GetRoot().ChildNodes.ToArray(); 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); var targetKernelName = DefaultLanguage; 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); } }