public MetadataReference CreateReference(ImmutableArray <string> aliases, bool embedInteropTypes, DocumentationProvider documentationProvider) { if (this.IsEmpty) { return(null); } // first see whether we can use native memory directly. var stream = this.storage.ReadStream(); var supportNativeMemory = stream as ISupportDirectMemoryAccess; if (supportNativeMemory != null) { // this is unfortunate that if we give stream, compiler will just re-copy whole content to // native memory again. this is a way to get around the issue by we getting native memory ourselves and then // give them pointer to the native memory. also we need to handle lifetime ourselves. var referenceWithNativeMemory = new MetadataImageReference( AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length)), documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: this.assemblyName); // tie lifetime of stream to metadata reference we created. native memory's lifetime is tied to // stream internally and stream is shared between same temporary storage. so here, we should be // sharing same native memory for all skeleton assemblies from same project snapshot. lifetime.GetValue(referenceWithNativeMemory, _ => stream); return(referenceWithNativeMemory); } // otherwise, we just let it use stream. unfortunately, if we give stream, compiler will // internally copy it to native memory again. since compiler owns lifetime of stream, // it would be great if compiler can be little bit smarter on how it deals with stream. return(new MetadataImageReference( stream, documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: this.assemblyName)); }
public MetadataReference CreateReference(ImmutableArray<string> aliases, bool embedInteropTypes, DocumentationProvider documentationProvider) { if (this.IsEmpty) { return null; } // first see whether we can use native memory directly. var stream = this.storage.ReadStream(); var supportNativeMemory = stream as ISupportDirectMemoryAccess; if (supportNativeMemory != null) { // this is unfortunate that if we give stream, compiler will just re-copy whole content to // native memory again. this is a way to get around the issue by we getting native memory ourselves and then // give them pointer to the native memory. also we need to handle lifetime ourselves. var referenceWithNativeMemory = new MetadataImageReference( AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length)), documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: this.assemblyName); // tie lifetime of stream to metadata reference we created. native memory's lifetime is tied to // stream internally and stream is shared between same temporary storage. so here, we should be // sharing same native memory for all skeleton assemblies from same project snapshot. lifetime.GetValue(referenceWithNativeMemory, _ => stream); return referenceWithNativeMemory; } // otherwise, we just let it use stream. unfortunately, if we give stream, compiler will // internally copy it to native memory again. since compiler owns lifetime of stream, // it would be great if compiler can be little bit smarter on how it deals with stream. return new MetadataImageReference( stream, documentation: documentationProvider, aliases: aliases, embedInteropTypes: embedInteropTypes, display: this.assemblyName); }
public void TestAddMetadataReferences() { var csharpReference = new MetadataImageReference(GetResourceBytes(@"CSharpProject.dll").AsImmutable()); var solution = CreateSolution(); var project1 = ProjectId.CreateNewId(); solution = solution.AddProject(project1, "foo", "foo.dll", LanguageNames.CSharp); solution = solution.AddMetadataReference(project1, mscorlib); // For CSharp Reference solution = solution.AddMetadataReference(project1, csharpReference); var assemblyReference = (IAssemblySymbol)solution.GetProject(project1).GetCompilationAsync().Result.GetAssemblyOrModuleSymbol(csharpReference); var namespacesAndTypes = assemblyReference.GlobalNamespace.GetAllNamespacesAndTypes(CancellationToken.None); var foundSymbol = from symbol in namespacesAndTypes where symbol.Name.Equals("CSharpClass") select symbol; Assert.Equal(1, foundSymbol.Count()); solution = solution.RemoveMetadataReference(project1, csharpReference); assemblyReference = (IAssemblySymbol)solution.GetProject(project1).GetCompilationAsync().Result.GetAssemblyOrModuleSymbol(csharpReference); Assert.Null(assemblyReference); ValidateSolutionAndCompilations(solution); }
public override bool Execute() { var files = InputFiles.Select(f => new SourceFile { Name = f.ItemSpec, SyntaxTree = SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f.ItemSpec)) }).ToList(); // Creation of the assembly reference should be done this way: // var mscorlib = new MetadataFileReference(typeof(object).Assembly.Location); // But this creates a "path not absolute" exception on mono in GetAssemblyOrModuleSymbol() below. // See http://stackoverflow.com/questions/26355922/creating-roslyn-metadatafilereference-bombs-on-mono-linux var mscorlibMetadata = AssemblyMetadata.CreateFromImageStream(new FileStream(typeof(object).Assembly.Location, FileMode.Open, FileAccess.Read)); var mscorlib = new MetadataImageReference (mscorlibMetadata); var datalibMetadata = AssemblyMetadata.CreateFromImageStream(new FileStream(typeof(CommandBehavior).Assembly.Location, FileMode.Open, FileAccess.Read)); var datalib = new MetadataImageReference (datalibMetadata); var compilation = CSharpCompilation.Create( "Temp", files.Select(f => f.SyntaxTree), new[] { mscorlib, datalib } ); foreach (var file in files) { file.SemanticModel = compilation.GetSemanticModel(file.SyntaxTree); } var corlibSymbol = (IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(mscorlib); _excludedTypes = new HashSet<ITypeSymbol> { corlibSymbol.GetTypeByMetadataName("System.IO.TextWriter"), corlibSymbol.GetTypeByMetadataName("System.IO.MemoryStream") }; // First pass: find methods with the [GenerateAsync] attribute foreach (var file in files) { foreach (var m in file.SyntaxTree.GetRoot() .DescendantNodes() .OfType<MethodDeclarationSyntax>() ) { // Syntactically filter out any method without [GenerateAsync] (for performance) if (m.AttributeLists.SelectMany(al => al.Attributes).All(a => a.Name.ToString() != "GenerateAsync")) { continue; } var methodSymbol = file.SemanticModel.GetDeclaredSymbol(m); var cls = m.FirstAncestorOrSelf<ClassDeclarationSyntax>(); var ns = cls.FirstAncestorOrSelf<NamespaceDeclarationSyntax>(); Dictionary<ClassDeclarationSyntax, HashSet<MethodInfo>> classes; if (!file.NamespaceToClasses.TryGetValue(ns, out classes)) classes = file.NamespaceToClasses[ns] = new Dictionary<ClassDeclarationSyntax, HashSet<MethodInfo>>(); HashSet<MethodInfo> methods; if (!classes.TryGetValue(cls, out methods)) methods = classes[cls] = new HashSet<MethodInfo>(); var methodInfo = new MethodInfo { DeclarationSyntax = m, Symbol = methodSymbol, Transformed = m.Identifier.Text + "Async", WithOverride = false }; var attr = methodSymbol.GetAttributes().Single(a => a.AttributeClass.Name == "GenerateAsync"); if (attr.ConstructorArguments[0].Value != null) methodInfo.Transformed = (string)attr.ConstructorArguments[0].Value; if (((bool) attr.ConstructorArguments[1].Value)) methodInfo.WithOverride = true; methods.Add(methodInfo); } } Log.LogMessage("Found {0} methods marked for async rewriting", files.SelectMany(f => f.NamespaceToClasses.Values).SelectMany(ctm => ctm.Values).SelectMany(m => m).Count()); // Second pass: transform foreach (var f in files) { Log.LogMessage("Writing out {0}", f.TransformedName); File.WriteAllText(f.TransformedName, RewriteFile(f).ToString()); } OutputFiles = files.Select(f => new TaskItem(f.TransformedName)).ToArray(); return true; }