Пример #1
0
        /// <summary>
        /// Generates an assembly from a source and a minimal list of required reference assemblies.
        /// </summary>
        /// <param name="code">The source code.</param>
        /// <param name="assemblyPath">The full final assembly path (including the .dll extension). Can be null if skipCompilation is true.</param>
        /// <param name="skipCompilation">True to skip the compilation. Only the parsing and the source generation is done.</param>
        /// <param name="loader">Optional loader function to load the final emitted assembly.</param>
        /// <returns>Encapsulation of the result.</returns>
        public GenerateResult Generate(ICodeWorkspace code, string assemblyPath, bool skipCompilation, Func <string, Assembly>?loader = null)
        {
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }
            using (var weakLoader = WeakAssemblyNameResolver.TemporaryInstall())
            {
                var input = GeneratorInput.Create(_workspaceFactory, code, Modules, !skipCompilation && AutoRegisterRuntimeAssembly, ParseOptions);
                Modules.Clear();

                if (skipCompilation)
                {
                    return(new GenerateResult(input.Trees));
                }

                var collector = new HashSet <Assembly>();
                foreach (var a in input.Assemblies)
                {
                    if (collector.Add(a))
                    {
                        Discover(a, collector);
                    }
                }
                return(Generate(CompilationOptions,
                                input.Trees,
                                assemblyPath,
                                collector.Select(a => MetadataReference.CreateFromFile(new Uri(a.Location).LocalPath)),
                                loader)
                       .WithLoadFailures(weakLoader.Conflicts));
            }
        }
Пример #2
0
 public void Inject(ICodeWorkspace code)
 {
     code.Global
     .EnsureUsing("System")
     .CreateType("public static class RealDBNull")
     .Append("public static object V = DBNull.Value;").NewLine();
 }
Пример #3
0
        public void BuildGenericMethods()
        {
            ICodeWorkspace  workspace = CodeWorkspace.Create();
            INamespaceScope global    = workspace.Global;
            INamespaceScope b         = global.FindOrCreateNamespace("CK._g");

            Type t = typeof(ContainsGenericMethods <>);

            workspace.EnsureAssemblyReference(t);

            b.EnsureUsing(t.Namespace);
            var c = b.CreateType(header => header.Append("class Specialized<T> : ").AppendCSharpName(t, true, true, true).NewLine());

            c.CreateOverride(t.GetMethod("Simple1"))
            .Append("if (arg.Equals(default(T))) throw new System.ArgumentException();").NewLine()
            .Append("return default(TResult);");

            c.CreateOverride(t.GetMethod("Simple2"))
            .Append("=> arg2 is T1;");

            Assembly a = TestHelper.CreateAssembly(workspace.GetGlobalSource(), workspace.AssemblyReferences);

            Type tC = a.GetTypes().Single(n => n.Name == "Specialized`1").MakeGenericType(typeof(int));
            ContainsGenericMethods <int> gotIt = (ContainsGenericMethods <int>)Activator.CreateInstance(tC);

            gotIt.Simple1 <bool>(25).Should().BeFalse();
            gotIt.Simple2(new object(), "test").Should().BeTrue();
        }
Пример #4
0
 public CodeProjectImpl(string projectName, ICodeWorkspace code)
 {
     Code             = code;
     ProjectName      = projectName;
     TargetFrameworks = new HashSet <string>();
     Sdk = "Microsoft.NET.Sdk";
     PackageReferences = new List <PackageReference>();
 }
Пример #5
0
        public void using_alias_are_a_bit_normalized_by_removing_white_spaces()
        {
            ICodeWorkspace  workspace = CreateWorkspace();
            INamespaceScope global    = workspace.Global;
            INamespaceScope nAXa      = global.FindOrCreateNamespace("A.X.a");
            INamespaceScope nAXb      = global.FindOrCreateNamespace("A.X.b");
            INamespaceScope nAX       = global.FindOrCreateNamespace("A.X");
            INamespaceScope nA        = global.FindOrCreateNamespace("A");

            global.EnsureUsingAlias("INT", "System.UInt8");
            nAXa.EnsureUsingAlias("INT", "System . UInt8");

            ExtractNamespaces(global).Should().OnlyContain(x => x == "INT");
            ExtractNamespaces(nAXa).Should().BeEmpty();

            var source = workspace.GetGlobalSource();

            Normalize(source).Should().Be(Normalize(
                                              @"namespace A
{
using INT = System.UInt8;
namespace X
    {
        namespace a { }
        namespace b { }
    }
}"
                                              ));

            global.EnsureUsingAlias("CNode", "SNode<string,bool>");
            nAXa.EnsureUsingAlias("CNode", "SNode<STRING, BOOL>");
            nAXa.Append("// The 2 CNode definition differ.").NewLine();

            ExtractNamespaces(global).Should().HaveCount(2).And.OnlyContain(x => x == "INT" || x == "CNode");
            ExtractNamespaces(nAXa).Should().OnlyContain(x => x == "CNode");

            global.FindOrCreateNamespace("ToShowTheTopLevelUsingsCopy");
            source = workspace.GetGlobalSource();
            Normalize(source).Should().Be(Normalize(
                                              @"namespace A {
                    using INT = System.UInt8;
                    using CNode = SNode<string,bool>;
                    namespace X {
                      namespace a {
                        using CNode = SNode<STRING, BOOL>;
                        // The 2 CNode definition differ.
                      }
                      namespace b {
                      }
                    }
                  }
namespace ToShowTheTopLevelUsingsCopy
{
                    using INT = System.UInt8;
                    using CNode = SNode<string,bool>;
}"
                                              ));
        }
Пример #6
0
 public void Inject(ICodeWorkspace code)
 {
     code.Global
     .EnsureUsing("System")
     .EnsureUsing("System.Reflection")
     .Append(
         @"static class CKFixDBNull
             { 
                 // This was the original required code (before netcoreapp2.0):
                 // public static object Value = typeof( object ).Assembly.GetType( ""System.DBNull"" ).GetField( ""Value"" ).GetValue( null );
                 // Here we use a stupid value for the demo.
                 public static object Value = ""I'm the DBNull."";
             }");
 }
Пример #7
0
 public void MergeWith(ICodeWorkspace other)
 {
     if (other == null)
     {
         throw new ArgumentNullException(nameof(other));
     }
     if (other != this)
     {
         foreach (var a in other.AssemblyReferences)
         {
             _assemblies.Add(a);
         }
         Global.MergeWith((NamespaceScopeImpl)other.Global);
     }
 }
Пример #8
0
        public void BaseTest()
        {
            ICodeWorkspace  workspace = CodeWorkspace.Create();
            INamespaceScope global    = workspace.Global;
            INamespaceScope b         = global.FindOrCreateNamespace("CK._g");

            Type t = typeof(BaseToBeOverridden);

            workspace.EnsureAssemblyReference(t);

            b.EnsureUsing("System")
            .EnsureUsing("System.Collections.Generic")
            .EnsureUsing(t.Namespace);

            var c = b.CreateType(h => h.Append("class Specialized : ").AppendCSharpName(t, true, true, true));

            c.CreatePassThroughConstructors(t);

            c.CreateOverride(t.GetMethod("Simple1"))
            .Append("=> 3712;");

            c.CreateOverride(t.GetMethod("VoidMethod"));

            c.CreateOverride(t.GetMethod("Simple2", BindingFlags.Instance | BindingFlags.NonPublic))
            .Append("=> x + '-' + g.ToString();");

            c.CreateOverride(t.GetMethod("Simple3", BindingFlags.Instance | BindingFlags.NonPublic))
            .Append("g = Guid.NewGuid();").NewLine()
            .Append(@"x = ""Hello World!"" + Simple2( ""YES"", g );").NewLine()
            .Append("return this;");

            c.CreateOverride(t.GetMethod("VerbatimParameters", BindingFlags.Instance | BindingFlags.NonPublic)).Append(" => @this + @operator;");

            Assembly a = TestHelper.CreateAssembly(workspace.GetGlobalSource(), workspace.AssemblyReferences);

            Type tC = a.GetTypes().Single(n => n.Name == "Specialized");
            BaseToBeOverridden gotIt = (BaseToBeOverridden)Activator.CreateInstance(tC, new object[] { 3712 * 3712 });

            gotIt.ValFromCtor.Should().Be(3712 * 3712);
            gotIt.Simple1().Should().Be(3712);
            string s;
            Guid   g = Guid.Empty;

            gotIt.Simple3(out s, ref g, 9).Should().BeSameAs(gotIt);
            s.Should().Be("Hello World!YES-" + g.ToString());
            g.Should().NotBeEmpty();
        }
Пример #9
0
        /// <summary>
        /// Combines code workspaces and modules into a <see cref="GeneratorInput"/>.
        /// </summary>
        /// <param name="workspaceFactory">Factory for <see cref="ICodeWorkspace"/> implementations. Must not be null.</param>
        /// <param name="code">Original code. Can be null or empty.</param>
        /// <param name="modules">Code modules. Can be null or empty.</param>
        /// <param name="addRuntimeAssembly">True to automatically add the typeof(object)'s assembly.</param>
        /// <param name="options">The optional parse options to use.</param>
        /// <returns>A generator input.</returns>
        internal static GeneratorInput Create(
            Func <ICodeWorkspace> workspaceFactory,
            ICodeWorkspace code,
            IEnumerable <ICodeGeneratorModule> modules,
            bool addRuntimeAssembly,
            CSharpParseOptions?options)
        {
            Debug.Assert(workspaceFactory != null);
            var assemblies = new HashSet <Assembly>();

            if (addRuntimeAssembly)
            {
                assemblies.Add(typeof(object).Assembly);
            }
            var trees = new List <SyntaxTree>();

            if (code != null)
            {
                CombineWorkspace(assemblies, trees, code, options);
            }
            if (modules != null)
            {
                foreach (var m in modules)
                {
                    var transformed = m.Rewrite(trees);
                    if (transformed != null && transformed != trees)
                    {
                        trees.Clear();
                        trees.AddRange(transformed);
                    }
                    var wM = workspaceFactory();
                    m.Inject(wM);
                    CombineWorkspace(assemblies, trees, wM, options);
                }
            }
            return(new GeneratorInput(assemblies, trees));
        }
Пример #10
0
        public void SqlTest()
        {
            ICodeWorkspace  workspace = CodeWorkspace.Create();
            INamespaceScope global    = workspace.Global;
            INamespaceScope b         = global.FindOrCreateNamespace("CK._g");

            workspace.EnsureAssemblyReference(typeof(SqlCommand), typeof(SimpleBase));

            b.EnsureUsing("System")
            .EnsureUsing("System.Collections.Generic")
            .EnsureUsing("Microsoft.Data.SqlClient");

            var type = b.CreateType(w => w.Append("public class GGGG : ").AppendCSharpName(typeof(SimpleBase), true, true, true));

            type.CreateOverride(typeof(SimpleBase).GetMethod("Do"))
            .Append(
                @"if( i.HasValue )
                {
                    i *= i;
                }
                var c = new SqlCommand(""p""+i.ToString());
                var p = c.Parameters.AddWithValue(""@i"", (object)i ?? DBNull.Value);
                return c;");

            var source     = workspace.GetGlobalSource();
            var references = workspace.AssemblyReferences;

            Assembly   a     = TestHelper.CreateAssembly(source, references);
            Type       t     = a.GetTypes().Single(n => n.Name == "GGGG");
            SimpleBase gotIt = (SimpleBase)Activator.CreateInstance(t);
            int?       k     = 67;
            SqlCommand cmd   = gotIt.Do(ref k);

            k.Should().Be(67 * 67);
            cmd.CommandText.Should().Be("p" + k);
            cmd.Parameters.Cast <SqlParameter>().Single().Value.Should().Be(k);
        }
Пример #11
0
        static void CombineWorkspace(HashSet <Assembly> assemblies, List <SyntaxTree> trees, ICodeWorkspace c, CSharpParseOptions?options)
        {
            foreach (var a in c.AssemblyReferences)
            {
                assemblies.Add(a);
            }
            var s = c.GetGlobalSource();

            if (!String.IsNullOrWhiteSpace(s))
            {
                trees.Add(SyntaxFactory.ParseSyntaxTree(s, options));
            }
        }
Пример #12
0
 /// <summary>
 /// Writes the current <see cref="ICodeWorkspace.Global">Global</see> source code into a <see cref="TextWriter"/>.
 /// </summary>
 /// <param name="this">This wokspace.</param>
 /// <param name="w">Target TextWriter.</param>
 public static void WriteGlobalSource(this ICodeWorkspace @this, TextWriter w)
 {
     @this.Global.Build(w.Write, true);
 }
Пример #13
0
 /// <summary>
 /// Gets the current <see cref="ICodeWorkspace.Global">Global</see> source code.
 /// This is the same as calling ToString() on the Global namespace.
 /// </summary>
 /// <param name="this">This wokspace.</param>
 /// <returns>The current code source for this workspace.</returns>
 public static string GetGlobalSource(this ICodeWorkspace @this)
 {
     return(@this.Global.Build(new StringBuilder(), true).ToString());
 }
Пример #14
0
 public Tracker(ICodeWorkspace w)
 {
     w.NamespaceCreated += OnNamespaceCreated;
     w.TypeCreated      += OnTypeCreated;
     w.FunctionCreated  += OnFunctionCreated;
 }