Example #1
0
        /// <summary>
        /// Logs the content of each file in the given compilation as Information using the given logger.
        /// 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 ArgumentNullException if the given compilation is null.
        /// </summary>
        private static void PrintFileContentInMemory(Compilation compilation, ILogger logger)
        {
            if (compilation == null)
            {
                throw new ArgumentNullException(nameof(compilation));
            }
            foreach (var file in compilation.SourceFiles)
            {
                IEnumerable <string> inMemory = compilation.FileContent[file];
                var stripWrapping             = Options.IsCodeSnippet(file);
                QsCompilerError.Verify(!stripWrapping || inMemory.Count() >= 4,
                                       "expecting at least four lines of code for the compilation of a code snippet");

                if (stripWrapping)
                {
                    inMemory = inMemory.Skip(2).Take(inMemory.Count() - 4);
                }
                logger.Log(
                    InformationCode.FileContentInMemory,
                    Enumerable.Empty <string>(),
                    stripWrapping ? null : file.Value,
                    messageParam: $"{Environment.NewLine}{String.Concat(inMemory)}"
                    );
            }
        }
Example #2
0
        /// <summary>
        /// Logs 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 PrintSyntaxTree(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)
            {
                var stripWrapping = Options.IsCodeSnippet(file);
                var subtree       = evaluatedTree.Select(ns => FilterBySourceFile.Apply(ns, file)).Where(ns => ns.Elements.Any());

                void PrintTree(string serialization) => logger.Log(
                    InformationCode.BuiltSyntaxTree,
                    Enumerable.Empty <string>(),
                    stripWrapping ? null : file.Value,
                    messageParam: new string[] { "", serialization });

                if (!stripWrapping)
                {
                    PrintTree(JsonConvert.SerializeObject(subtree, Newtonsoft.Json.Formatting.Indented));
                }
                else
                {
                    PrintTree(JsonConvert.SerializeObject(StripSnippetWrapping(subtree), Newtonsoft.Json.Formatting.Indented));
                }
            }
        }
Example #3
0
        /// <summary>
        /// Logs the tokenization of each file in the given compilation as Information using the given logger.
        /// If the id of a file is consistent with the one assigned to a code snippet,
        /// strips the tokens that correspond to the wrapping defined by WrapSnippet.
        /// Throws an ArgumentNullException if the given compilation is null.
        /// </summary>
        private static void PrintContentTokenization(Compilation compilation, ILogger logger)
        {
            if (compilation == null)
            {
                throw new ArgumentNullException(nameof(compilation));
            }
            foreach (var file in compilation.SourceFiles)
            {
                var tokenization  = compilation.Tokenization[file].Select(tokens => tokens.Select(token => token.Kind));
                var stripWrapping = Options.IsCodeSnippet(file);
                QsCompilerError.Verify(!stripWrapping || tokenization.Count() >= 4,
                                       "expecting at least four lines of code for the compilation of a code snippet");

                if (stripWrapping)
                {
                    tokenization = tokenization.Skip(2).Take(tokenization.Count() - 4).ToImmutableArray();
                }
                var serialization = tokenization
                                    .Select(line => line.Select(item => JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)))
                                    .Zip(Enumerable.Range(1, tokenization.Count()),
                                         (ts, i) => ts.Any() ? $"\n[ln {i}]: \n{String.Join("\n", ts)} \n" : "");

                serialization = new string[] { "" }.Concat(serialization);
                logger.Log(
                    InformationCode.BuiltTokenization,
                    Enumerable.Empty <string>(),
                    stripWrapping ? null : file.Value,
                    messageParam: serialization.ToArray()
                    );
            }
        }
Example #4
0
        /// <summary>
        /// Generates formatted Q# code for the file with the given uri based on the syntax tree in the given compilation.
        /// If the id of the file is consistent with the one assigned to a code snippet,
        /// logs the generated code using the given logger.
        /// Creates a file containing the generated code in the given output folder otherwise.
        /// Returns true if the generation succeeded, and false if an exception was thrown.
        /// Throws an ArgumentNullException if the given compilation, the file uri or its absolute path are null.
        /// </summary>
        private static bool GenerateFormattedQsFile(Compilation compilation, NonNullable <string> fileName, string outputFolder, ILogger logger)
        {
            if (compilation == null)
            {
                throw new ArgumentNullException(nameof(compilation));
            }

            var code = Enumerable.Empty <string>();

            try { code = code.Concat(GenerateQsCode(compilation, fileName, logger).Where(c => !String.IsNullOrWhiteSpace(c))); }
            catch (Exception ex)
            {
                logger?.Log(ErrorCode.QsGenerationFailed, Enumerable.Empty <string>(), fileName.Value);
                logger?.Log(ex);
                return(false);
            }

            if (Options.IsCodeSnippet(fileName))
            {
                code = new string[] { "" }.Concat(Formatting.Indent(code.ToArray()));
                logger?.Log(InformationCode.GeneratedQsCode, Enumerable.Empty <string>(), messageParam: code.ToArray());
            }
            else
            {
                var content = String.Join(Environment.NewLine, code.Select(block => $"{block}{Environment.NewLine}{Environment.NewLine}"));
                CompilationLoader.GeneratedFile(fileName, outputFolder ?? "FormattedFiles", ".qs", content);
            }
            return(true);
        }
Example #5
0
        /// <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(SyntaxTreeToQsharp.Default.ToCode));
            }
            else
            {
                var imports = compilation.SyntaxTree.Values
                              .ToImmutableDictionary(ns => ns.Name, ns => compilation.OpenDirectives(file, ns.Name).ToImmutableArray());
                var success = SyntaxTreeToQsharp.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);
                }));
            }
        }
Example #6
0
        /// <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());
                };
            }
        }