示例#1
0
            /// <summary>
            /// Generates the assembly from the specified importing options.
            /// </summary>
            /// <param name="options">The importing options.</param>
            internal ImportUserTypeAssembly GenerateAssembly(ImportUserTypeOptions options)
            {
                // Generate CodeGen configuration
                string    assemblyPath  = Path.Combine(Path.GetTempPath(), "CsDebugScript.CodeGen.Assemblies", Guid.NewGuid().ToString() + ".dll");
                XmlConfig codeGenConfig = ConvertOptionsToCodeGenConfig(options);

                codeGenConfig.GeneratedAssemblyName = assemblyPath;

                // Execute code generation
                IModuleProvider moduleProvider = new EngineSymbolProviderModuleProvider(Process.Current);
                Generator       generator      = new Generator(moduleProvider);

                byte[] assemblyBytes = generator.GenerateAssembly(codeGenConfig);

                Directory.CreateDirectory(Path.GetDirectoryName(assemblyPath));
                File.WriteAllBytes(assemblyPath, assemblyBytes);

                // Add generated file to be loaded after execution
                return(new ImportUserTypeAssembly()
                {
                    AssemblyBytes = assemblyBytes,
                    AssemblyPath = assemblyPath,
                    Options = options,
                });
            }
示例#2
0
        /// <summary>
        /// Converts the importing options to CodeGen configuration.
        /// </summary>
        /// <param name="options">The importing options.</param>
        /// <returns>CodeGen configuration</returns>
        private static XmlConfig ConvertOptionsToCodeGenConfig(ImportUserTypeOptions options)
        {
            // User types
            List <XmlType> types = new List <XmlType>();

            foreach (string userTypeName in options.UserTypes)
            {
                types.Add(new XmlType()
                {
                    Name = userTypeName,
                    ExportDependentTypes = options.ImportDependentTypes,
                });
            }

            // Modules
            List <XmlModule> modules = new List <XmlModule>();

            foreach (string moduleName in options.Modules)
            {
                Module module      = Module.All.First(m => m.Name == moduleName);
                string symbolsPath = Context.SymbolProvider.GetModuleSymbolsPath(module);

                if (!File.Exists(symbolsPath))
                {
                    continue;
                }
                modules.Add(new XmlModule()
                {
                    Name        = moduleName,
                    SymbolsPath = symbolsPath,
                });
            }

            // Check if we are using direct class access.
            bool useDirectClassAccess = !(Context.SymbolProvider is DbgEngSymbolProvider);

            // Create configuration
            return(new XmlConfig()
            {
                Types = types.ToArray(),
                Modules = modules.ToArray(),
                UseDirectClassAccess = useDirectClassAccess,
                CompressedOutput = true,
                ForceUserTypesToNewInsteadOfCasting = true,
                GeneratePhysicalMappingOfUserTypes = useDirectClassAccess,
                MultiFileExport = false,
                Transformations = DefaultTransformations,
                GenerateAssemblyWithILWriter = options.UseILCodeWriter,
            });
        }
示例#3
0
            /// <summary>
            /// Normalizes specified source path with respect to base file path.
            /// </summary>
            /// <param name="path">The source path to normalize. May be absolute or relative.</param>
            /// <param name="baseFilePath">Path of the source file that contains the <paramref name="path" /> (may also be relative), or null if not available.</param>
            /// <returns>
            /// Normalized path, or null if <paramref name="path" /> can't be normalized. The resulting path doesn't need to exist.
            /// </returns>
            public override string NormalizePath(string path, string baseFilePath)
            {
                // Try to see if it is import user type options
                ImportUserTypeOptions options = ImportUserTypeOptions.ParseString(path);

                if (options != null)
                {
                    return(options.Serialize());
                }

                // Normalize path
                string result = originalSourceResolver.NormalizePath(path, baseFilePath);

                return(result);
            }
示例#4
0
        /// <summary>
        /// Imports user types from modules using the specified importing options.
        /// </summary>
        /// <param name="options">The importing options.</param>
        /// <param name="asAssembly">If set to <c>true</c> user types will be imported as assembly. If set to <c>false</c> user types will be imported as script code.</param>
        public void ImportUserTypes(ImportUserTypeOptions options, bool asAssembly = false)
        {
            if (asAssembly)
            {
                ImportUserTypeAssembly assembly = _AssemblyResolver_.GenerateAssembly(options);

                _CodeGenAssemblies_.Add(assembly);
            }
            else
            {
                ImportUserTypeCode code = _CodeResolver_.GenerateCode(options);

                _CodeGenCode_.Add(code);
            }
        }
示例#5
0
            /// <summary>
            /// Generates the code from the specified importing options.
            /// </summary>
            /// <param name="options">The importing options.</param>
            internal ImportUserTypeCode GenerateCode(ImportUserTypeOptions options)
            {
                XmlConfig codeGenConfig = ConvertOptionsToCodeGenConfig(options);

                codeGenConfig.GenerateNamespaceAsStaticClass = true;

                // Execute code generation
                IModuleProvider moduleProvider = new EngineSymbolProviderModuleProvider(Process.Current);
                Generator       generator      = new Generator(moduleProvider);
                string          code           = generator.GenerateScriptCode(codeGenConfig);

                // Add generated code to be loaded after execution
                return(new ImportUserTypeCode()
                {
                    Code = code,
                    Options = options,
                });
            }
示例#6
0
        /// <summary>
        /// Converts the importing options to CodeGen configuration.
        /// </summary>
        /// <param name="options">The importing options.</param>
        /// <returns>CodeGen configuration</returns>
        private static XmlConfig ConvertOptionsToCodeGenConfig(ImportUserTypeOptions options)
        {
            // User types
            List <XmlType> types = new List <XmlType>();

            foreach (string userTypeName in options.UserTypes)
            {
                types.Add(new XmlType()
                {
                    Name = userTypeName,
                    ExportDependentTypes = options.ImportDependentTypes,
                });
            }

            // Modules
            List <XmlModule> modules = new List <XmlModule>();

            foreach (string moduleName in options.Modules)
            {
                modules.Add(new XmlModule()
                {
                    Name    = moduleName,
                    PdbPath = Module.All.First(m => m.Name == moduleName).SymbolFileName,
                });
            }

            // Check if we are using DIA as symbol provider
            bool useDia = Context.SymbolProvider is DiaSymbolProvider;

            // Create configuration
            return(new XmlConfig()
            {
                Types = types.ToArray(),
                Modules = modules.ToArray(),
                UseDiaSymbolProvider = useDia,
                CompressedOutput = true,
                ForceUserTypesToNewInsteadOfCasting = true,
                GeneratePhysicalMappingOfUserTypes = useDia,
                MultiFileExport = false,
                Transformations = DefaultTransformations,
            });
        }
示例#7
0
            /// <summary>
            /// Opens a <see cref="T:System.IO.Stream" /> that allows reading the content of the specified file.
            /// </summary>
            /// <param name="resolvedPath">Path returned by <see cref="M:Microsoft.CodeAnalysis.SourceReferenceResolver.ResolveReference(System.String,System.String)" />.</param>
            /// <returns></returns>
            public override Stream OpenRead(string resolvedPath)
            {
                ImportUserTypeCode code;

                if (codeGenCode.TryGetValue(resolvedPath, out code))
                {
                    return(new MemoryStream(Encoding.UTF8.GetBytes(code.Code)));
                }

                ImportUserTypeOptions options = ImportUserTypeOptions.ParseString(resolvedPath);

                if (options != null)
                {
                    code = GenerateCode(options);
                    AddCode(code);
                    return(new MemoryStream(Encoding.UTF8.GetBytes(code.Code)));
                }

                return(originalSourceResolver.OpenRead(resolvedPath));
            }
示例#8
0
            /// <summary>
            /// Resolves specified path with respect to base file path.
            /// </summary>
            /// <param name="path">The path to resolve. May be absolute or relative.</param>
            /// <param name="baseFilePath">Path of the source file that contains the <paramref name="path" /> (may also be relative), or null if not available.</param>
            /// <returns>
            /// Normalized path, or null if the file can't be resolved.
            /// </returns>
            public override string ResolveReference(string path, string baseFilePath)
            {
                // Try to see if it is import user type options
                ImportUserTypeOptions options = ImportUserTypeOptions.ParseString(path);

                if (options != null)
                {
                    return(options.Serialize());
                }

                // Do resolve reference
                string result = originalSourceResolver.ResolveReference(path, baseFilePath);

                if (string.IsNullOrEmpty(result))
                {
                    result = ResolvePath(path, baseFilePath);
                }

                return(result);
            }
示例#9
0
            /// <summary>
            /// Resolves the reference.
            /// </summary>
            /// <param name="reference">The reference.</param>
            /// <param name="baseFilePath">The base file path.</param>
            /// <param name="properties">The properties.</param>
            /// <returns></returns>
            public override ImmutableArray <PortableExecutableReference> ResolveReference(string reference, string baseFilePath, MetadataReferenceProperties properties)
            {
                // Check if we are referencing CodeGen assembly
                ImportUserTypeAssembly codeGenAssembly;

                if (codeGenAssemblies.TryGetValue(reference, out codeGenAssembly))
                {
                    using (MemoryStream stream = new MemoryStream(codeGenAssembly.AssemblyBytes))
                    {
                        return(ImmutableArray.Create(MetadataReference.CreateFromStream(stream, properties, null, codeGenAssembly.AssemblyPath)));
                    }
                }

                // Check the previous resolver
                var result = previousResolver.ResolveReference(reference, baseFilePath, properties);

                if (result.Length > 0)
                {
                    return(result);
                }

                // Try to use file resolver
                try
                {
                    string path = ResolvePath(reference, baseFilePath);

                    if (!string.IsNullOrEmpty(path))
                    {
                        return(ImmutableArray.Create(MetadataReference.CreateFromFile(path, properties)));
                    }
                }
                catch
                {
                }

                // Check if reference holds xml for CodeGen
                ImportUserTypeOptions options = ImportUserTypeOptions.ParseString(reference);

                if (options != null)
                {
                    foreach (ImportUserTypeAssembly assembly in codeGenAssemblies.Values)
                    {
                        if (assembly.Options.Equals(options))
                        {
                            // TODO: Compare that used PDBs have same GUID.
                            codeGenAssembly = assembly;
                            break;
                        }
                    }

                    if (codeGenAssembly == null)
                    {
                        codeGenAssembly = GenerateAssembly(options);
                        AddAssembly(codeGenAssembly);
                    }

                    using (MemoryStream stream = new MemoryStream(codeGenAssembly.AssemblyBytes))
                    {
                        return(ImmutableArray.Create(MetadataReference.CreateFromStream(stream, properties, null, codeGenAssembly.AssemblyPath)));
                    }
                }

                return(ImmutableArray <PortableExecutableReference> .Empty);
            }