public static IAssemblySymbol GetCompilation(Stream stream, Stream documentationStream)
        {
            PortableExecutableReference reference;

            using (var memoryStream = new MemoryStream())
            {
                stream.CopyTo(memoryStream);
                memoryStream.Position = 0;

                DocumentationProvider documentation = null;
                if (documentationStream != null)
                {
                    using var docMemoryStream = new MemoryStream();
                    documentationStream.CopyTo(docMemoryStream);
                    docMemoryStream.Position = 0;
                    documentation            = XmlDocumentationProvider.CreateFromBytes(docMemoryStream.ToArray());
                }
                // MetadataReference.CreateFromStream closes the stream
                reference = MetadataReference.CreateFromStream(memoryStream, documentation: documentation);
            }
            var compilation    = CSharpCompilation.Create(null).AddReferences(reference);
            var corlibLocation = typeof(object).Assembly.Location;

            var runtimeFolder = Path.GetDirectoryName(corlibLocation);

            compilation = compilation.AddReferences(MetadataReference.CreateFromFile(corlibLocation));

            var trustedAssemblies = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")).Split(Path.PathSeparator);

            foreach (var tpl in trustedAssemblies)
            {
                if (tpl.StartsWith(runtimeFolder) || AllowedAssemblies.Contains(Path.GetFileNameWithoutExtension(tpl)))
                {
                    compilation = compilation.AddReferences(MetadataReference.CreateFromFile(tpl));
                }
            }

            return((IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(reference));
        }
Example #2
0
        static async Task Main(string[] args)
        {
            var rootFolder = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, @"../../../../.."));
            var srcFolder  = Path.Combine(rootFolder, "src");

            // Hack re-add System.Runtime.Intrinsics with doc
            // @"packs/Microsoft.NETCore.App.Ref/5.0.0/ref/net5.0";

            var instances = MSBuildLocator.QueryVisualStudioInstances(new VisualStudioInstanceQueryOptions()
            {
                DiscoveryTypes = DiscoveryType.DotNetSdk, WorkingDirectory = AppContext.BaseDirectory
            });

            MetadataReference intrinsicsAssembly = null;

            foreach (var instance in instances)
            {
                var file = Path.GetFullPath(Path.Combine(instance.MSBuildPath, "..", "..", "packs", "Microsoft.NETCore.App.Ref", "5.0.0", "ref", "net5.0", "System.Runtime.Intrinsics.xml"));
                if (File.Exists(file))
                {
                    var docText = File.ReadAllText(file);
                    foreach (var fixDocPair in FixIntrinsicsDocumentation)
                    {
                        docText = docText.Replace(fixDocPair.Key, fixDocPair.Value);
                    }

                    var docProvider  = XmlDocumentationProvider.CreateFromBytes(new UTF8Encoding(false).GetBytes(docText));
                    var assemblyPath = Path.ChangeExtension(file, "dll");
                    intrinsicsAssembly = MetadataReference.CreateFromFile(assemblyPath, MetadataReferenceProperties.Assembly, docProvider);
                    break;
                }
            }

            if (intrinsicsAssembly == null)
            {
                Console.WriteLine("Unable to find System.Runtime.Intrinsics.xml from dotnet SDK installed");
                Environment.Exit(1);
                return;
            }

            var workspace = new AdhocWorkspace();
            var project   = workspace.AddProject("Temp", LanguageNames.CSharp);

            project = project.AddMetadataReference(intrinsicsAssembly);
            workspace.TryApplyChanges(project.Solution);

            // Make sure that doc will be parsed
            project = project.WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
            project = project.WithParseOptions(project.ParseOptions.WithDocumentationMode(DocumentationMode.Parse));

            // Compile the project
            var compilation = await project.GetCompilationAsync();

            var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToList();

            if (errors.Count > 0)
            {
                Console.WriteLine("Compilation errors:");
                foreach (var error in errors)
                {
                    Console.WriteLine(error);
                }

                Console.WriteLine("Error, Exiting.");
                Environment.Exit(1);
                return;
            }

            var intrinsicModules = FindIntrinsics(compilation);


            var templateStr = @"//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Date: {{ date.now }}
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;

{{~ for module in intrinsics ~}}
namespace {{ module.Namespace }}
{
    public partial class {{ module.ClassName }}
    {
        public const string Category = ""{{ module.Category }}"";

        {{~ for member in module.Members ~}}
        /// <summary>
        /// {{ member.Description | string.replace '\n' '\n        ///' }}
        {{~ for param in member.Parameters ~}}
        /// <param name=""{{param.Name}}"">{{param.Description}}</param>
        {{~ end ~}}
        /// </summary>
        [KalkExport(""{{ member.Name }}"", Category)]
        {{ member.MethodDeclaration }}
        {{ member.IndirectMethodDeclaration }}
        {{~ end ~}}
    }
}
{{~ end ~}}
";

            var template  = Template.Parse(templateStr);
            var result    = template.Render(new { intrinsics = intrinsicModules }, x => x.Name);
            var finalPath = Path.Combine(srcFolder, "Kalk.Core/Modules/HardwareIntrinsics/Intrinsics.generated.cs");

            Console.WriteLine($"Writing intrinsics to {finalPath}");
            // Replace with platform newlines
            result = result.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
            await File.WriteAllTextAsync(finalPath, result, new UTF8Encoding(false));
        }
Example #3
0
        public IEnumerable <IDocument> Execute(IReadOnlyList <IDocument> inputs, IExecutionContext context)
        {
            List <ISymbol> symbols = new List <ISymbol>();

            // Create the compilation (have to supply an XmlReferenceResolver to handle include XML doc comments)
            MetadataReference mscorlib    = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
            Compilation       compilation = CSharpCompilation
                                            .Create(CompilationAssemblyName)
                                            .WithReferences(mscorlib)
                                            .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
                                                                                      xmlReferenceResolver: new XmlFileResolver(context.FileSystem.RootPath.FullPath)));

            // Handle input documents
            if (_inputDocuments)
            {
                // Get syntax trees (supply path so that XML doc includes can be resolved)
                ConcurrentBag <SyntaxTree> syntaxTrees = new ConcurrentBag <SyntaxTree>();
                context.ParallelForEach(inputs, input =>
                {
                    using (Stream stream = input.GetStream())
                    {
                        SourceText sourceText = SourceText.From(stream);
                        syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText,
                                                                   path: input.String(Keys.SourceFilePath, string.Empty)));
                    }
                });

                compilation = compilation.AddSyntaxTrees(syntaxTrees);
            }

            // Handle assemblies
            IEnumerable <IFile> assemblyFiles = context.FileSystem.GetInputFiles(_assemblyGlobs)
                                                .Where(x => (x.Path.Extension == ".dll" || x.Path.Extension == ".exe") && x.Exists);

            MetadataReference[] assemblyReferences = assemblyFiles.Select(assemblyFile =>
            {
                // Create the metadata reference for the compilation
                IFile xmlFile = context.FileSystem.GetFile(assemblyFile.Path.ChangeExtension("xml"));
                if (xmlFile.Exists)
                {
                    Trace.Verbose($"Creating metadata reference for assembly {assemblyFile.Path.FullPath} with XML documentation file");
                    using (Stream xmlStream = xmlFile.OpenRead())
                    {
                        using (MemoryStream xmlBytes = new MemoryStream())
                        {
                            xmlStream.CopyTo(xmlBytes);
                            return(MetadataReference.CreateFromStream(assemblyFile.OpenRead(),
                                                                      documentation: XmlDocumentationProvider.CreateFromBytes(xmlBytes.ToArray())));
                        }
                    }
                }
                Trace.Verbose($"Creating metadata reference for assembly {assemblyFile.Path.FullPath} without XML documentation file");
                return((MetadataReference)MetadataReference.CreateFromStream(assemblyFile.OpenRead()));
            }).ToArray();
            if (assemblyReferences.Length > 0)
            {
                compilation = compilation.AddReferences(assemblyReferences);
                symbols.AddRange(assemblyReferences
                                 .Select(x => (IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(x))
                                 .Select(x => _assemblySymbols ? x : (ISymbol)x.GlobalNamespace));
            }

            // Get and return the document tree
            symbols.Add(compilation.Assembly.GlobalNamespace);
            AnalyzeSymbolVisitor visitor = new AnalyzeSymbolVisitor(compilation, context, _symbolPredicate,
                                                                    _writePath ?? (x => DefaultWritePath(x, _writePathPrefix)),
                                                                    _cssClasses, _docsForImplicitSymbols, _assemblySymbols);

            foreach (ISymbol symbol in symbols)
            {
                visitor.Visit(symbol);
            }
            return(visitor.Finish());
        }