<commit_before>﻿// -----------------------------------------------------------------------
// <copyright file="CsCompiler.cs" company="(none)">
//   Copyright © 2014 <NAME>.  All Rights Reserved.
//   This source is subject to the MIT license.
//   Please see license.md for more information.
// </copyright>
// -----------------------------------------------------------------------

namespace Pegasus.Workbench.Pipeline
{
    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Linq;
    using System.Reactive.Concurrency;
    using System.Reactive.Linq;
    using Microsoft.CSharp;
    using Pegasus.Common;
    using Pegasus.Expressions;

    internal sealed class CsCompiler : IDisposable
    {
        private readonly IDisposable disposable;

        public CsCompiler(IObservable<Tuple<string, Grammar>> codeAndGrammar, IObservable<string> fileNames)
        {
            var csCompilerResults = codeAndGrammar
                .CombineLatest(fileNames, (cg, fileName) => new { code = cg.Item1, grammar = cg.Item2, fileName })
                .Throttle(TimeSpan.FromMilliseconds(10), Scheduler.Default)
                .Select(p => Compile(p.code, p.grammar, p.fileName))
                .Publish();

            this.Parsers = csCompilerResults.Select(r => r.Parser);
            this.Errors = csCompilerResults.Select(r => r.Errors.AsReadOnly());

            this.disposable = csCompilerResults.Connect();
        }

        public IObservable<IList<CompilerError>> Errors { get; private set; }

        public IObservable<dynamic> Parsers { get; private set; }

        public void Dispose()
        {
            this.disposable.Dispose();
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Any exception that happens during compilation should be reported through the UI.")]
        private static Result Compile(string source, Grammar grammar, string fileName)
        {
            if (source == null || grammar == null)
            {
                return new Result
                {
                    Errors = new List<CompilerError>(),
                };
            }

            CompilerResults compilerResults;
            using (var compiler = new CSharpCodeProvider())
            {
                var options = new CompilerParameters
                {
                    GenerateExecutable = false,
                    GenerateInMemory = true,
                };
                options.ReferencedAssemblies.Add("System.dll");
                options.ReferencedAssemblies.Add("System.Core.dll");
                options.ReferencedAssemblies.Add(typeof(Cursor).Assembly.Location);

                compilerResults = compiler.CompileAssemblyFromSource(options, source);
            }

            var fileDirectory = Path.GetDirectoryName(fileName);
            var fileFileName = Path.GetFileName(fileName);

            var errors = (from CompilerError e in compilerResults.Errors
                          let errorFileName = Path.GetFileName(e.FileName)
                          let newName = errorFileName.Equals(fileFileName, StringComparison.CurrentCultureIgnoreCase) ? fileFileName : fileFileName + ".cs"<commit_msg>Added dynamic support.<commit_after>﻿// -----------------------------------------------------------------------
// <copyright file="CsCompiler.cs" company="(none)">
//   Copyright © 2014 <NAME>.  All Rights Reserved.
//   This source is subject to the MIT license.
//   Please see license.md for more information.
// </copyright>
// -----------------------------------------------------------------------

namespace Pegasus.Workbench.Pipeline
{
    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Linq;
    using System.Reactive.Concurrency;
    using System.Reactive.Linq;
    using Microsoft.CSharp;
    using Pegasus.Common;
    using Pegasus.Expressions;

    internal sealed class CsCompiler : IDisposable
    {
        private readonly IDisposable disposable;

        public CsCompiler(IObservable<Tuple<string, Grammar>> codeAndGrammar, IObservable<string> fileNames)
        {
            var csCompilerResults = codeAndGrammar
                .CombineLatest(fileNames, (cg, fileName) => new { code = cg.Item1, grammar = cg.Item2, fileName })
                .Throttle(TimeSpan.FromMilliseconds(10), Scheduler.Default)
                .Select(p => Compile(p.code, p.grammar, p.fileName))
                .Publish();

            this.Parsers = csCompilerResults.Select(r => r.Parser);
            this.Errors = csCompilerResults.Select(r => r.Errors.AsReadOnly());

            this.disposable = csCompilerResults.Connect();
        }

        public IObservable<IList<CompilerError>> Errors { get; private set; }

        public IObservable<dynamic> Parsers { get; private set; }

        public void Dispose()
        {
            this.disposable.Dispose();
        }

        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Any exception that happens during compilation should be reported through the UI.")]
        private static Result Compile(string source, Grammar grammar, string fileName)
        {
            if (source == null || grammar == null)
            {
                return new Result
                {
                    Errors = new List<CompilerError>(),
                };
            }

            CompilerResults compilerResults;
            using (var compiler = new CSharpCodeProvider())
            {
                var options = new CompilerParameters
                {
                    GenerateExecutable = false,
                    GenerateInMemory = true,
                };
                options.ReferencedAssemblies.Add("System.dll");
                options.ReferencedAssemblies.Add("System.Core.dll");
                options.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
                options.ReferencedAssemblies.Add(typeof(Cursor).Assembly.Location);

                compilerResults = compiler.CompileAssemblyFromSource(options, source);
            }

            var fileDirectory = Path.GetDirectoryName(fileName);
            var fileFileName = Path.GetFileName(fileName);

            var errors = (from CompilerError e in compilerResults.Errors
                          let errorFileName = Path.GetFileName(e.FileName)
                          let newName = errorFileName.Equals(fileFileName, StringComparison.CurrentCultureIgnoreCase) ? fileFileName : fileFileName + ".cs"
{'fraction_non_alphanumeric': 0.130647311509406, 'fraction_numerical': 0.0035550288846096876, 'mean_word_length': 1.8990983254615714, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2387257', 'n_tokens_mistral': 1700, 'n_tokens_neox': 1599, 'n_words': 376}