/// <summary> /// Logs the generated Q# code for the part of the given evaluated syntax tree that corresponds to each file /// in the given compilation as Information using the given logger. /// If the given evaluated tree is null, queries the tree contained in the given compilation instead. /// If the id of a file is consistent with the one assigned to a code snippet, /// strips the lines of code that correspond to the wrapping defined by WrapSnippet. /// Throws an ArgumentException if this is not possible because the given syntax tree is inconsistent with that wrapping. /// Throws an ArgumentNullException if the given compilation is null. /// </summary> private static void PrintGeneratedQs(IEnumerable <QsNamespace> evaluatedTree, Compilation compilation, ILogger logger) { if (compilation == null) { throw new ArgumentNullException(nameof(compilation)); } evaluatedTree = evaluatedTree ?? compilation.SyntaxTree.Values; foreach (var file in compilation.SourceFiles) { if (Options.IsCodeSnippet(file)) { var subtree = evaluatedTree.Select(ns => FilterBySourceFile.Apply(ns, file)).Where(ns => ns.Elements.Any()); var code = new string[] { "" }.Concat(StripSnippetWrapping(subtree).Select(FormatCompilation.FormatStatement)); logger.Log(InformationCode.FormattedQsCode, Enumerable.Empty <string>(), messageParam: code.ToArray()); } else { var imports = evaluatedTree.ToImmutableDictionary(ns => ns.Name, ns => compilation.OpenDirectives(file, ns.Name).ToImmutableArray()); SyntaxTreeToQs.Apply(out List <ImmutableDictionary <NonNullable <string>, string> > generated, evaluatedTree, (file, imports)); var code = new string[] { "" }.Concat(generated.Single().Values.Select(nsCode => $"{nsCode}{Environment.NewLine}")); logger.Log(InformationCode.FormattedQsCode, Enumerable.Empty <string>(), file.Value, messageParam: code.ToArray()); }; } }
/// <summary> /// Generates formatted Q# code based on the part of the syntax tree that corresponds to each file in the given compilation. /// If the id of a file is consistent with the one assigned to a code snippet, /// strips the lines of code that correspond to the wrapping defined by WrapSnippet. /// Throws an ArgumentException if this is not possible because the given syntax tree is inconsistent with that wrapping. /// Throws an ArgumentNullException if the given compilation is null. /// </summary> private static IEnumerable <string> GenerateQsCode(Compilation compilation, NonNullable <string> file, ILogger logger) { if (compilation == null) { throw new ArgumentNullException(nameof(compilation)); } if (Options.IsCodeSnippet(file)) { var subtree = compilation.SyntaxTree.Values.Select(ns => FilterBySourceFile.Apply(ns, file)).Where(ns => ns.Elements.Any()); return(DiagnoseCompilation.StripSnippetWrapping(subtree).Select(FormatStatement)); } else { var imports = compilation.SyntaxTree.Values .ToImmutableDictionary(ns => ns.Name, ns => compilation.OpenDirectives(file, ns.Name).ToImmutableArray()); var success = SyntaxTreeToQs.Apply(out List <ImmutableDictionary <NonNullable <string>, string> > generated, compilation.SyntaxTree.Values, (file, imports)); if (!success) { logger?.Log(WarningCode.UnresolvedItemsInGeneratedQs, Enumerable.Empty <string>(), file.Value); } return(generated.Single().Select(entry => { var nsComments = compilation.NamespaceComments(file, entry.Key); string FormatComments(IEnumerable <string> comments) => String.Join(Environment.NewLine, comments.Select(line => line.Trim()).Select(line => String.IsNullOrWhiteSpace(line) ? "" : $"// {line}") ).Trim(); var leadingComments = entry.Value.StartsWith("///") ? $"{FormatComments(nsComments.OpeningComments)}{Environment.NewLine}" : FormatComments(nsComments.OpeningComments); var trailingComments = FormatComments(nsComments.ClosingComments); var code = new string[] { leadingComments, entry.Value, trailingComments }.Where(s => !String.IsNullOrWhiteSpace(s)); return String.Join(Environment.NewLine, code); })); }; }