/// <summary>
        /// Produces a <see cref="SymbolTreeInfo"/> for a given <see cref="PortableExecutableReference"/>.
        /// Note: can return <code>null</code> if we weren't able to actually load the metadata for some
        /// reason.
        /// </summary>
        public static Task<SymbolTreeInfo> TryGetInfoForMetadataReferenceAsync(
            Solution solution,
            PortableExecutableReference reference,
            bool loadOnly,
            CancellationToken cancellationToken)
        {
            var metadataId = GetMetadataIdNoThrow(reference);
            if (metadataId == null)
            {
                return SpecializedTasks.Default<SymbolTreeInfo>();
            }

            // Try to acquire the data outside the lock.  That way we can avoid any sort of 
            // allocations around acquiring the task for it.  Note: once ValueTask is available
            // (and enabled in the language), we'd likely want to use it here. (Presuming 
            // the lock is not being held most of the time).
            if (s_metadataIdToInfo.TryGetValue(metadataId, out var infoTask))
            {
                return infoTask;
            }

            var metadata = GetMetadataNoThrow(reference);
            if (metadata == null)
            {
                return SpecializedTasks.Default<SymbolTreeInfo>();
            }

            return TryGetInfoForMetadataReferenceSlowAsync(
                solution, reference, loadOnly, metadata, cancellationToken);
        }
        /// <summary>
        /// this gives you SymbolTreeInfo for a metadata
        /// </summary>
        public static async Task<SymbolTreeInfo> GetInfoForMetadataReferenceAsync(
            Solution solution,
            PortableExecutableReference reference,
            bool loadOnly,
            CancellationToken cancellationToken)
        {
            var metadata = reference.GetMetadata();
            if (metadata == null)
            {
                return null;
            }

            // Find the lock associated with this piece of metadata.  This way only one thread is
            // computing a symbol tree info for a particular piece of metadata at a time.
            var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback);
            using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                cancellationToken.ThrowIfCancellationRequested();

                SymbolTreeInfo info;
                if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info))
                {
                    return info;
                }

                info = await LoadOrCreateMetadataSymbolTreeInfoAsync(
                    solution, reference, loadOnly, cancellationToken: cancellationToken).ConfigureAwait(false);
                if (info == null && loadOnly)
                {
                    return null;
                }

                return s_metadataIdToInfo.GetValue(metadata.Id, _ => info);
            }
        }
 private static Metadata GetMetadataNoThrow(PortableExecutableReference reference)
 {
     try
     {
         return reference.GetMetadata();
     }
     catch (Exception e) when (e is BadImageFormatException || e is IOException)
     {
         return null;
     }
 }
 public MetadataSearchScope(
     Solution solution,
     IAssemblySymbol assembly,
     PortableExecutableReference metadataReference,
     bool ignoreCase,
     CancellationToken cancellationToken)
     : base(ignoreCase, cancellationToken)
 {
     _solution = solution;
     _assembly = assembly;
     _metadataReference = metadataReference;
 }
 private static Task<SymbolTreeInfo> LoadOrCreateMetadataSymbolTreeInfoAsync(
     Solution solution,
     PortableExecutableReference reference,
     bool loadOnly,
     CancellationToken cancellationToken)
 {
     var filePath = reference.FilePath;
     return LoadOrCreateAsync(
         solution,
         filePath,
         loadOnly,
         create: version => CreateMetadataSymbolTreeInfo(solution, version, reference, cancellationToken),
         keySuffix: "",
         getVersion: info => info._version,
         readObject: reader => ReadSymbolTreeInfo(reader, (version, nodes) => GetSpellCheckerTask(solution, version, filePath, nodes)),
         writeObject: (w, i) => i.WriteTo(w),
         cancellationToken: cancellationToken);
 }
        private static SymbolTreeInfo CreateMetadataSymbolTreeInfo(
            Solution solution, VersionStamp version, PortableExecutableReference reference, CancellationToken cancellationToken)
        {
            var unsortedNodes = new List<Node> { new Node("", Node.RootNodeParentIndex) };

            foreach (var moduleMetadata in GetModuleMetadata(reference.GetMetadata()))
            {
                MetadataReader reader;
                try
                {
                    reader = moduleMetadata.GetMetadataReader();
                }
                catch (BadImageFormatException)
                {
                    continue;
                }

                GenerateMetadataNodes(reader, unsortedNodes);
            }

            return CreateSymbolTreeInfo(solution, version, reference.FilePath, unsortedNodes);
        }
Beispiel #7
0
        private static async Task FindImmediateMatchingMetadataTypesInMetadataReferenceAsync(
            HashSet <INamedTypeSymbol> metadataTypes,
            Project project,
            Func <HashSet <INamedTypeSymbol>, INamedTypeSymbol, bool> metadataTypeMatches,
            Compilation compilation,
            PortableExecutableReference reference,
            HashSet <INamedTypeSymbol> result,
            CancellationToken cancellationToken)
        {
            // We store an index in SymbolTreeInfo of the *simple* metadata type name
            // to the names of the all the types that either immediately derive or
            // implement that type.  Because the mapping is from the simple name
            // we might get false positives.  But that's fine as we still use
            // 'metadataTypeMatches' to make sure the match is correct.
            var symbolTreeInfo = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                project.Solution, reference, loadOnly : false, cancellationToken : cancellationToken).ConfigureAwait(false);

            // For each type we care about, see if we can find any derived types
            // in this index.
            foreach (var metadataType in metadataTypes)
            {
                var baseTypeName = metadataType.Name;

                // For each derived type we find, see if we can map that back
                // to an actual symbol.  Then check if that symbol actually fits
                // our criteria.
                foreach (var derivedType in symbolTreeInfo.GetDerivedMetadataTypes(baseTypeName, compilation, cancellationToken))
                {
                    if (derivedType != null && derivedType.Locations.Any(s_isInMetadata))
                    {
                        if (metadataTypeMatches(metadataTypes, derivedType))
                        {
                            result.Add(derivedType);
                        }
                    }
                }
            }
        }
        private static async Task <SymbolTreeInfo> GetInfoForMetadataReferenceSlowAsync(
            Solution solution, PortableExecutableReference reference, Checksum checksum,
            bool loadOnly, Metadata metadata, CancellationToken cancellationToken)
        {
            // Find the lock associated with this piece of metadata.  This way only one thread is
            // computing a symbol tree info for a particular piece of metadata at a time.
            var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback);

            using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (s_metadataIdToInfo.TryGetValue(metadata.Id, out var infoTask))
                {
                    var oldInfo = await infoTask.ConfigureAwait(false);

                    if (oldInfo.Checksum == checksum)
                    {
                        return(oldInfo);
                    }
                }

                var info = await TryLoadOrCreateMetadataSymbolTreeInfoAsync(
                    solution, reference, checksum, loadOnly, cancellationToken).ConfigureAwait(false);

                if (info == null && loadOnly)
                {
                    return(CreateEmpty(checksum));
                }

                // Cache the result in our dictionary.  Store it as a completed task so that
                // future callers don't need to allocate to get the result back.
                infoTask = Task.FromResult(info);
                s_metadataIdToInfo.Remove(metadata.Id);
                s_metadataIdToInfo.Add(metadata.Id, infoTask);

                return(info);
            }
        }
        /// <summary>
        /// Produces a <see cref="SymbolTreeInfo"/> for a given <see cref="PortableExecutableReference"/>.
        /// Note:  will never return null;
        /// </summary>
        public static async Task <SymbolTreeInfo> GetInfoForMetadataReferenceAsync(
            Solution solution,
            PortableExecutableReference reference,
            Checksum checksum,
            bool loadOnly,
            CancellationToken cancellationToken)
        {
            var metadataId = GetMetadataIdNoThrow(reference);

            if (metadataId == null)
            {
                return(CreateEmpty(checksum));
            }

            // Try to acquire the data outside the lock.  That way we can avoid any sort of
            // allocations around acquiring the task for it.  Note: once ValueTask is available
            // (and enabled in the language), we'd likely want to use it here. (Presuming
            // the lock is not being held most of the time).
            if (s_metadataIdToInfo.TryGetValue(metadataId, out var infoTask))
            {
                var info = await infoTask.ConfigureAwait(false);

                if (info.Checksum == checksum)
                {
                    return(info);
                }
            }

            var metadata = GetMetadataNoThrow(reference);

            if (metadata == null)
            {
                return(CreateEmpty(checksum));
            }

            return(await GetInfoForMetadataReferenceSlowAsync(
                       solution, reference, checksum, loadOnly, metadata, cancellationToken).ConfigureAwait(false));
        }
Beispiel #10
0
        /// <summary>
        /// this gives you SymbolTreeInfo for a metadata
        /// </summary>
        public static async Task <SymbolTreeInfo> GetInfoForMetadataReferenceAsync(
            Solution solution,
            PortableExecutableReference reference,
            bool loadOnly,
            CancellationToken cancellationToken)
        {
            var metadata = GetMetadataNoThrow(reference);

            if (metadata == null)
            {
                return(null);
            }

            // Find the lock associated with this piece of metadata.  This way only one thread is
            // computing a symbol tree info for a particular piece of metadata at a time.
            var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback);

            using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                cancellationToken.ThrowIfCancellationRequested();

                SymbolTreeInfo info;
                if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info))
                {
                    return(info);
                }

                info = await LoadOrCreateMetadataSymbolTreeInfoAsync(
                    solution, reference, loadOnly, cancellationToken : cancellationToken).ConfigureAwait(false);

                if (info == null && loadOnly)
                {
                    return(null);
                }

                return(s_metadataIdToInfo.GetValue(metadata.Id, _ => info));
            }
        }
Beispiel #11
0
        /// <summary>
        /// If the extended <paramref name="reference"/> is a .Net Assembly return a <see cref="MetadataReader"/>
        /// instance that can be used to read the assembly's embedded metadata, otherwise return null.
        /// </summary>
        /// <param name="reference"> The extended <see cref="PortableExecutableReference"/>. </param>
        /// <returns> A <see cref="MetadataReader"/> if the reference is a .Net assembly or null otherwise. </returns>
        public static MetadataReader?GetMetadataReader(this PortableExecutableReference reference)
        {
            try
            {
                if (reference.GetMetadata() is AssemblyMetadata assembly)
                {
                    foreach (var module in assembly.GetModules())
                    {
                        return(module.GetMetadataReader());
                    }
                }
                else if (reference.GetMetadata() is ModuleMetadata module)
                {
                    return(module.GetMetadataReader());
                }

                return(null);
            }
            catch (BadImageFormatException)
            {
                return(null);
            }
        }
Beispiel #12
0
        private static Checksum GetMetadataChecksumSlow(
            Solution solution,
            PortableExecutableReference reference,
            CancellationToken cancellationToken
            )
        {
            return(ChecksumCache.GetOrCreate(
                       reference,
                       _ =>
            {
                var serializer = solution.Workspace.Services.GetService <ISerializerService>();
                var checksum = serializer.CreateChecksum(reference, cancellationToken);

                // Include serialization format version in our checksum.  That way if the
                // version ever changes, all persisted data won't match the current checksum
                // we expect, and we'll recompute things.
                return Checksum.Create(
                    WellKnownSynchronizationKind.SymbolTreeInfo,
                    new[] { checksum, SerializationFormatChecksum }
                    );
            }
                       ));
        }
Beispiel #13
0
        private static async Task AddMetadataDeclarationsWithNormalQueryAsync(
            Project project, IAssemblySymbol assembly, PortableExecutableReference referenceOpt,
            SearchQuery query, SymbolFilter filter, ArrayBuilder <SymbolAndProjectId> list,
            CancellationToken cancellationToken)
        {
            // All entrypoints to this function are Find functions that are only searching
            // for specific strings (i.e. they never do a custom search).
            Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API");

            using (Logger.LogBlock(FunctionId.SymbolFinder_Assembly_AddDeclarationsAsync, cancellationToken))
            {
                if (referenceOpt != null)
                {
                    var info = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                        project.Solution, referenceOpt, loadOnly : false, cancellationToken : cancellationToken).ConfigureAwait(false);

                    var symbols = await info.FindAsync(
                        query, assembly, project.Id, filter, cancellationToken).ConfigureAwait(false);

                    list.AddRange(symbols);
                }
            }
        }
Beispiel #14
0
        private void WriteMvidsTo(PortableExecutableReference reference, ObjectWriter writer, CancellationToken cancellationToken)
        {
            var metadata = GetMetadata(reference);

            var assemblyMetadata = metadata as AssemblyMetadata;

            if (assemblyMetadata != null)
            {
                writer.WriteInt32((int)assemblyMetadata.Kind);

                var modules = assemblyMetadata.GetModules();
                writer.WriteInt32(modules.Length);

                foreach (var module in modules)
                {
                    WriteMvidTo(module, writer, cancellationToken);
                }

                return;
            }

            WriteMvidTo((ModuleMetadata)metadata, writer, cancellationToken);
        }
Beispiel #15
0
        public async Task CheckPEReferencesNotSameAfterReferenceChangedTest()
        {
            using var ws = new AdhocWorkspace();
            var projectInfo = ProjectInfo.Create(
                ProjectId.CreateNewId(),
                VersionStamp.Create(),
                "TestProject",
                "TestProject",
                LanguageNames.CSharp,
                metadataReferences: ImmutableArray.Create <MetadataReference>(
                    PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location)
                    )
                );

            var project = ws.AddProject(projectInfo);

            // get original references
            var compilation1 = await project.GetCompilationAsync();

            var references1 = compilation1.ExternalReferences;

            // explicitly change references
            var forkedProject = project.WithMetadataReferences(
                ImmutableArray.Create <MetadataReference>(
                    PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location),
                    PortableExecutableReference.CreateFromFile(typeof(Workspace).Assembly.Location)
                    )
                );

            // get new compilation
            var compilation2 = await forkedProject.GetCompilationAsync();

            var references2 = compilation2.ExternalReferences;

            Assert.NotEqual(references1, references2);
        }
Beispiel #16
0
        public void GetTopLevelTypesFromPEReference(
            Solution solution,
            Compilation compilation,
            PortableExecutableReference peReference,
            SyntaxContext syntaxContext,
            Action <CompletionItem, bool> handleItem,
            CancellationToken cancellationToken)
        {
            var key = GetReferenceKey(peReference);

            if (key == null)
            {
                // Can't cache items for reference with null key. We don't want risk potential perf regression by
                // making those items repeatedly, so simply not returning anything from this assembly, until
                // we have a better understanding on this sceanrio.
                // TODO: Add telemetry
                return;
            }

            if (!(compilation.GetAssemblyOrModuleSymbol(peReference) is IAssemblySymbol assemblySymbol))
            {
                return;
            }

            var checksum = SymbolTreeInfo.GetMetadataChecksum(solution, peReference, cancellationToken);

            GetAccessibleTopLevelTypesWorker(
                key,
                assemblySymbol,
                checksum,
                syntaxContext,
                handleItem,
                CacheService.PEItemsCache,
                cancellationToken);

            return;
        /// <summary>
        /// sample use of the CompileSource method.
        /// </summary>
        /// <param name="source1"></param>
        /// <param name="source2"></param>
        /// <returns></returns>
        public static Tuple <Assembly, IEnumerable <string> > CompileSourceDemo(
            string source1, string source2,
            PortableExecutableReference anotherReference)
        {
            IEnumerable <string> errmsgs = null;
            Assembly             assem   = null;

            {
                string[] sourceInput = new string[] { source1, source2 };
                var      rv          = CSharpCompilationExt.CompileSource(sourceInput, anotherReference);
                assem   = rv.Item1;
                errmsgs = rv.Item2;
            }

            if (errmsgs != null)
            {
                foreach (var errmsg in errmsgs)
                {
                    Debug.WriteLine(errmsg);
                }
            }

            return(new Tuple <Assembly, IEnumerable <string> >(assem, errmsgs));
        }
        public void ConfigureServices(IServiceCollection services)
        {
            PortableExecutableReference reference = MetadataReference.CreateFromFile(@"C:\{PathToTheProject}\AspNetCoreApplicationParts\src\AspNetCoreApplicationParts.ModuleA\bin\Debug\netstandard1.5\AspNetCoreApplicationParts.ModuleA.dll");
            Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(@"C:\{PathToTheProject}\AspNetCoreApplicationParts\src\AspNetCoreApplicationParts.ModuleA\bin\Debug\netstandard1.5\AspNetCoreApplicationParts.ModuleA.dll");

            services.AddMvc().AddApplicationPart(assembly).AddRazorOptions(
                o =>
            {
                o.FileProviders.Add(new EmbeddedFileProvider(assembly, assembly.GetName().Name));

                Action <RoslynCompilationContext> previous = o.CompilationCallback;

                o.CompilationCallback = c =>
                {
                    if (previous != null)
                    {
                        previous(c);
                    }

                    c.Compilation = c.Compilation.AddReferences(reference);
                };
            }
                );
        }
Beispiel #19
0
        private static SymbolTreeInfo CreateMetadataSymbolTreeInfo(
            Solution solution, VersionStamp version, PortableExecutableReference reference, CancellationToken cancellationToken)
        {
            var unsortedNodes = new List <Node> {
                new Node("", Node.RootNodeParentIndex)
            };

            foreach (var moduleMetadata in GetModuleMetadata(GetMetadataNoThrow(reference)))
            {
                MetadataReader reader;
                try
                {
                    reader = moduleMetadata.GetMetadataReader();
                }
                catch (BadImageFormatException)
                {
                    continue;
                }

                GenerateMetadataNodes(reader, unsortedNodes);
            }

            return(CreateSymbolTreeInfo(solution, version, reference.FilePath, unsortedNodes));
        }
        public void Analyze(
            string targetPath,
            Action <Diagnostic> reportDiagnostic,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            // Create a Roslyn representation of the IL by constructing a MetadataReference against
            // the target path (as if we intended to reference this binary during compilation, instead
            // of analyzing it). Using this mechanism, we can scan types/members contained in the
            // binary. We cannot currently retrieve IL from method bodies.
            PortableExecutableReference reference = MetadataReference.CreateFromFile(targetPath);
            var     compilation = CSharpCompilation.Create("_", references: new[] { reference });
            ISymbol target      = compilation.GetAssemblyOrModuleSymbol(reference);

            // For each analysis target, we create a compilation start context, which may result
            // in symbol action registration. We need to capture and throw these registrations
            // away for each binary we inspect.
            var compilationStartAnalysisContext = new RoslynCompilationStartAnalysisContext(compilation, _options, cancellationToken);

            this.GlobalRoslynAnalysisContext.CompilationStartActions?.Invoke(compilationStartAnalysisContext);

            var visitor = new RoslynSymbolVisitor(symbol => this.Analyze(
                                                      symbol,
                                                      compilation,
                                                      compilationStartAnalysisContext.SymbolActions,
                                                      reportDiagnostic,
                                                      cancellationToken));

            visitor.Visit(target);

            // Having finished analysis, we'll invoke any compilation end actions registered previously.
            // We also discard the per-compilation symbol actions we collected.
            var compilationAnalysisContext = new CompilationAnalysisContext(compilation, _options, reportDiagnostic, _isSupportedDiagnostic, cancellationToken);

            this.GlobalRoslynAnalysisContext.CompilationActions?.Invoke(compilationAnalysisContext);
            compilationStartAnalysisContext.CompilationEndActions?.Invoke(compilationAnalysisContext);
        }
        private static async Task AddDeclarationsAsync(
            Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt,
            SearchQuery query, SymbolFilter filter, ArrayBuilder <ISymbol> list, CancellationToken cancellationToken)
        {
            // All entrypoints to this function are Find functions that are only searching
            // for specific strings (i.e. they never do a custom search).
            Debug.Assert(query.Kind != SearchKind.Custom);

            using (Logger.LogBlock(FunctionId.SymbolFinder_Assembly_AddDeclarationsAsync, cancellationToken))
            {
                if (referenceOpt != null)
                {
                    var info = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                        solution, referenceOpt, loadOnly : false, cancellationToken : cancellationToken).ConfigureAwait(false);

                    if (info != null)
                    {
                        var symbols = await info.FindAsync(query, assembly, filter, cancellationToken).ConfigureAwait(false);

                        list.AddRange(symbols);
                    }
                }
            }
        }
Beispiel #22
0
        private static Task <SymbolTreeInfo> TryCreateMetadataSymbolTreeInfoAsync(
            HostWorkspaceServices services,
            SolutionKey solutionKey,
            PortableExecutableReference reference,
            Checksum checksum,
            StorageDatabase database,
            CancellationToken cancellationToken)
        {
            var filePath = reference.FilePath;

            var result = TryLoadOrCreateAsync(
                services,
                solutionKey,
                checksum,
                database,
                loadOnly: false,
                createAsync: () => CreateMetadataSymbolTreeInfoAsync(services, solutionKey, checksum, database, reference),
                keySuffix: "_Metadata_" + filePath,
                tryReadObject: reader => TryReadSymbolTreeInfo(reader, checksum, nodes => GetSpellCheckerAsync(services, solutionKey, checksum, database, filePath, nodes)),
                cancellationToken: cancellationToken);

            Contract.ThrowIfNull(result != null);
            return(result);
        }
 static bool ContainsPathComponent(PortableExecutableReference reference, string pathComponent)
 => PathUtilities.ContainsPathComponent(reference.FilePath, pathComponent, ignoreCase: true);
 private Metadata GetMetadata(PortableExecutableReference reference)
 {
     // TODO: right now, use reflection, but this API will be added as public API soon. when that happen, remove reflection
     var methodInfo = reference.GetType().GetTypeInfo().GetDeclaredMethod("GetMetadataImpl");
     return (Metadata)methodInfo.Invoke(reference, null);
 }
        private void WriteMvidsTo(PortableExecutableReference reference, ObjectWriter writer, CancellationToken cancellationToken)
        {
            var metadata = reference.GetMetadata();

            var assemblyMetadata = metadata as AssemblyMetadata;
            if (assemblyMetadata != null)
            {
                writer.WriteInt32((int)assemblyMetadata.Kind);

                var modules = assemblyMetadata.GetModules();
                writer.WriteInt32(modules.Length);

                foreach (var module in modules)
                {
                    WriteMvidTo(module, writer, cancellationToken);
                }

                return;
            }

            WriteMvidTo((ModuleMetadata)metadata, writer, cancellationToken);
        }
        protected void WritePortableExecutableReferenceHeaderTo(
            PortableExecutableReference reference, SerializationKinds kind, ObjectWriter writer, CancellationToken cancellationToken)
        {
            writer.WriteString(nameof(PortableExecutableReference));
            writer.WriteInt32((int)kind);

            WriteTo(reference.Properties, writer, cancellationToken);
            writer.WriteString(reference.FilePath);
        }
 void IVisualStudioWorkspaceHost.OnMetadataReferenceRemoved(ProjectId projectId, PortableExecutableReference metadataReference)
 {
     _workspace.OnMetadataReferenceRemoved(projectId, metadataReference);
 }
Beispiel #28
0
        private static async Task FindImmediateMatchingMetadataTypesInMetadataReferenceAsync(
            HashSet<INamedTypeSymbol> metadataTypes,
            Project project,
            Func<HashSet<INamedTypeSymbol>, INamedTypeSymbol, bool> metadataTypeMatches,
            Compilation compilation,
            PortableExecutableReference reference,
            HashSet<INamedTypeSymbol> result,
            CancellationToken cancellationToken)
        {
            // We store an index in SymbolTreeInfo of the *simple* metadata type name
            // to the names of the all the types that either immediately derive or 
            // implement that type.  Because the mapping is from the simple name
            // we might get false positives.  But that's fine as we still use 
            // 'metadataTypeMatches' to make sure the match is correct.
            var symbolTreeInfo = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                project.Solution, reference, loadOnly: false, cancellationToken: cancellationToken).ConfigureAwait(false);

            // For each type we care about, see if we can find any derived types
            // in this index.
            foreach (var metadataType in metadataTypes)
            {
                var baseTypeName = metadataType.Name;

                // For each derived type we find, see if we can map that back 
                // to an actual symbol.  Then check if that symbol actually fits
                // our criteria.
                foreach (var derivedType in symbolTreeInfo.GetDerivedMetadataTypes(baseTypeName, compilation, cancellationToken))
                {
                    if (derivedType != null && derivedType.Locations.Any(s_isInMetadata))
                    {
                        if (metadataTypeMatches(metadataTypes, derivedType))
                        {
                            result.Add(derivedType);
                        }
                    }
                }
            }
        }
        internal static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(
            Solution solution, IAssemblySymbol assembly, PortableExecutableReference reference, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken)
        {
            if (query.Name != null && string.IsNullOrWhiteSpace(query.Name))
            {
                return SpecializedCollections.EmptyEnumerable<ISymbol>();
            }

            var result = new List<ISymbol>();
            await AddDeclarationsAsync(solution, assembly, reference, query, filter, result, cancellationToken).ConfigureAwait(false);
            return result;
        }
 private static Metadata TryGetMetadata(PortableExecutableReference reference)
 {
     try
     {
         return reference.GetMetadata();
     }
     catch
     {
         // we have a reference but the file the reference is pointing to
         // might not actually exist on disk.
         // in that case, rather than crashing, we will handle it gracefully.
         return null;
     }
 }
 private void WritePortableExecutableReferencePropertiesTo(PortableExecutableReference reference, ObjectWriter writer, CancellationToken cancellationToken)
 {
     WriteTo(reference.Properties, writer, cancellationToken);
     writer.WriteString(reference.FilePath);
 }
 private static async Task AddDeclarationsAsync(
     Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt, SearchQuery query, SymbolFilter filter, List<ISymbol> list, CancellationToken cancellationToken)
 {
     using (Logger.LogBlock(FunctionId.SymbolFinder_Assembly_AddDeclarationsAsync, cancellationToken))
     {
         if (referenceOpt != null)
         {
             var info = await SymbolTreeInfo.TryGetInfoForAssemblyAsync(solution, assembly, referenceOpt, cancellationToken).ConfigureAwait(false);
             if (info != null)
             {
                 list.AddRange(FilterByCriteria(Find(query, info, assembly, cancellationToken), filter));
             }
         }
     }
 }
        private static async Task AddDeclarationsAsync(
            Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt, 
            SearchQuery query, SymbolFilter filter, ArrayBuilder<ISymbol> list, CancellationToken cancellationToken)
        {
            // All entrypoints to this function are Find functions that are only searching
            // for specific strings (i.e. they never do a custom search).
            Debug.Assert(query.Kind != SearchKind.Custom);

            using (Logger.LogBlock(FunctionId.SymbolFinder_Assembly_AddDeclarationsAsync, cancellationToken))
            {
                if (referenceOpt != null)
                {
                    var info = await SymbolTreeInfo.TryGetInfoForMetadataReferenceAsync(
                        solution, referenceOpt, loadOnly: false, cancellationToken: cancellationToken).ConfigureAwait(false);
                    if (info != null)
                    {
                        var symbols = await info.FindAsync(query, assembly, filter, cancellationToken).ConfigureAwait(false);
                        list.AddRange(symbols);
                    }
                }
            }
        }
 private static SymbolTreeInfo CreateMetadataSymbolTreeInfo(
     Solution solution, VersionStamp version,
     PortableExecutableReference reference,
     CancellationToken cancellationToken)
 {
     var creator = new MetadataInfoCreator(solution, version, reference, cancellationToken);
     return creator.Create();
 }
 private static string GetReferenceKey(PortableExecutableReference reference)
 {
     return reference.FilePath ?? reference.Display;
 }
Beispiel #36
0
 public unsafe static ModuleInstance Create(PortableExecutableReference reference)
 {
     // make a copy of the metadata, so that we don't dispose the metadata of a reference that are shared accross tests:
     return Create(reference.GetMetadata(), symReader: null, includeLocalSignatures: false);
 }
 int IEqualityComparer <PortableExecutableReference> .GetHashCode(PortableExecutableReference obj)
 {
     return(StringComparer.OrdinalIgnoreCase.GetHashCode(obj.FilePath ?? obj.Display));
 }
            private async Task UpdateReferenceAsync(
                Project project, Compilation compilation, PortableExecutableReference reference, CancellationToken cancellationToken)
            {
                var key = GetReferenceKey(reference);
                if (key == null)
                {
                    return;
                }

                DateTime lastWriteTime;
                if (!TryGetLastWriteTime(key, out lastWriteTime))
                {
                    // Couldn't get the write time.  Just ignore this reference.
                    return;
                }

                MetadataInfo metadataInfo;
                if (!_metadataPathToInfo.TryGetValue(key, out metadataInfo) || metadataInfo.TimeStamp == lastWriteTime)
                {
                    var info = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                        project.Solution, reference, loadOnly: false, cancellationToken: cancellationToken).ConfigureAwait(false);

                    metadataInfo = new MetadataInfo(lastWriteTime, info, metadataInfo.ReferencingProjects ?? new HashSet<ProjectId>());
                    _metadataPathToInfo.AddOrUpdate(key, metadataInfo, (_1, _2) => metadataInfo);
                }

                // Keep track that this dll is referenced by this project.
                metadataInfo.ReferencingProjects.Add(project.Id);
            }
Beispiel #39
0
        // 根据生成的类,动态编译把json转成protobuf
        private static void ExportExcelProtobuf(ConfigType configType)
        {
            string            classPath   = GetClassDir(configType);
            List <SyntaxTree> syntaxTrees = new List <SyntaxTree>();
            List <string>     protoNames  = new List <string>();

            foreach (string classFile in Directory.GetFiles(classPath, "*.cs"))
            {
                protoNames.Add(Path.GetFileNameWithoutExtension(classFile));
                syntaxTrees.Add(CSharpSyntaxTree.ParseText(File.ReadAllText(classFile)));
            }

            List <PortableExecutableReference> references = new List <PortableExecutableReference>();

            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assembly in assemblies)
            {
                try
                {
                    if (assembly.IsDynamic)
                    {
                        continue;
                    }

                    if (assembly.Location == "")
                    {
                        continue;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }

                PortableExecutableReference reference = MetadataReference.CreateFromFile(assembly.Location);
                references.Add(reference);
            }

            CSharpCompilation compilation = CSharpCompilation.Create(
                null,
                syntaxTrees.ToArray(),
                references.ToArray(),
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using MemoryStream memSteam = new MemoryStream();

            EmitResult emitResult = compilation.Emit(memSteam);

            if (!emitResult.Success)
            {
                StringBuilder stringBuilder = new StringBuilder();
                foreach (Diagnostic t in emitResult.Diagnostics)
                {
                    stringBuilder.AppendLine(t.GetMessage());
                }
                throw new Exception($"动态编译失败:\n{stringBuilder}");
            }

            memSteam.Seek(0, SeekOrigin.Begin);

            Assembly ass = Assembly.Load(memSteam.ToArray());

            string dir = GetProtoDir(configType);

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            foreach (string protoName in protoNames)
            {
                Type type    = ass.GetType($"ET.{protoName}Category");
                Type subType = ass.GetType($"ET.{protoName}");
                Serializer.NonGeneric.PrepareSerializer(type);
                Serializer.NonGeneric.PrepareSerializer(subType);


                string json        = File.ReadAllText(Path.Combine(string.Format(jsonDir, configType), $"{protoName}.txt"));
                object deserialize = BsonSerializer.Deserialize(json, type);

                string path = Path.Combine(dir, $"{protoName}Category.bytes");

                using FileStream file = File.Create(path);
                Serializer.Serialize(file, deserialize);
            }
        }
 private static async Task AddDeclarationsAsync(
     Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt, 
     SearchQuery query, SymbolFilter filter, List<ISymbol> list, CancellationToken cancellationToken)
 {
     using (Logger.LogBlock(FunctionId.SymbolFinder_Assembly_AddDeclarationsAsync, cancellationToken))
     {
         if (referenceOpt != null)
         {
             var info = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                 solution, referenceOpt, loadOnly: false, cancellationToken: cancellationToken).ConfigureAwait(false);
             if (info != null)
             {
                 var symbols = await info.FindAsync(query, assembly, filter, cancellationToken).ConfigureAwait(false);
                 list.AddRange(symbols);
             }
         }
     }
 }
        private Checksum CreatePortableExecutableReferenceChecksum(PortableExecutableReference reference, CancellationToken cancellationToken)
        {
            using (var stream = SerializableBytes.CreateWritableStream())
            using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken))
            {
                WriteMvidsTo(reference, writer, cancellationToken);

                stream.Position = 0;
                return Checksum.Create(stream);
            }
        }
Beispiel #42
0
        private static Task <SymbolTreeInfo> CreateMetadataSymbolTreeInfoAsync(
            HostWorkspaceServices services, SolutionKey solutionKey, Checksum checksum, StorageDatabase database, PortableExecutableReference reference)
        {
            var creator = new MetadataInfoCreator(services, solutionKey, checksum, database, reference);

            return(Task.FromResult(creator.Create()));
        }
        private void WritePortableExecutableReferenceTo(
            PortableExecutableReference reference, ObjectWriter writer, CancellationToken cancellationToken)
        {
            WritePortableExecutableReferenceHeaderTo(reference, SerializationKinds.Bits, writer, cancellationToken);

            WriteTo(reference.GetMetadata(), writer, cancellationToken);

            // TODO: what I should do with documentation provider? it is not exposed outside
        }
Beispiel #44
0
            public MetadataInfoCreator(
                HostWorkspaceServices services, SolutionKey solutionKey, Checksum checksum, StorageDatabase database, PortableExecutableReference reference)
            {
                _services                 = services;
                _solutionKey              = solutionKey;
                _checksum                 = checksum;
                _database                 = database;
                _reference                = reference;
                _metadataReader           = null;
                _allTypeDefinitions       = new List <MetadataDefinition>();
                _containsExtensionsMethod = false;

                _inheritanceMap = OrderPreservingMultiDictionary <string, string> .GetInstance();

                _parentToChildren = OrderPreservingMultiDictionary <MetadataNode, MetadataNode> .GetInstance();

                _extensionMethodToParameterTypeInfo = new MultiDictionary <MetadataNode, ParameterTypeInfo>();
                _rootNode = MetadataNode.Allocate(name: "");
            }
 /// <summary>
 /// We ignore references that are in a directory that contains the names
 /// "Packages", "packs", "NuGetFallbackFolder", or "NuGetPackages"
 /// These directories are most likely the ones produced by NuGet, and we don't want
 /// to offer to add .dll reference manually for dlls that are part of NuGet packages.
 ///
 /// Note that this is only a heuristic (though a good one), and we should remove this
 /// when we can get an API from NuGet that tells us if a reference is actually provided
 /// by a nuget packages.
 /// Tracking issue: https://github.com/dotnet/project-system/issues/5275
 ///
 /// This heuristic will do the right thing in practically all cases for all. It
 /// prevents the very unpleasant experience of us offering to add a direct metadata
 /// reference to something that should only be referenced as a nuget package.
 ///
 /// It does mean that if the following is true:
 /// You have a project that has a non-nuget metadata reference to something in a "packages"
 /// directory, and you are in another project that uses a type name that would have matched
 /// an accessible type from that dll. then we will not offer to add that .dll reference to
 /// that other project.
 ///
 /// However, that would be an exceedingly uncommon case that is degraded.  Whereas we're
 /// vastly improved in the common case. This is a totally acceptable and desirable outcome
 /// for such a heuristic.
 /// </summary>
 private bool IsInPackagesDirectory(PortableExecutableReference reference)
 {
     return(ContainsPathComponent(reference, "packages") ||
            ContainsPathComponent(reference, "packs") ||
            ContainsPathComponent(reference, "NuGetFallbackFolder") ||
            ContainsPathComponent(reference, "NuGetPackages"));
Beispiel #46
0
 private static void WritePortableExecutableReferencePropertiesTo(PortableExecutableReference reference, ObjectWriter writer, CancellationToken cancellationToken)
 {
     WriteTo(reference.Properties, writer, cancellationToken);
     writer.WriteString(reference.FilePath);
 }
            private void LoadReference(PortableExecutableReference resolvedReference, bool suppressWarnings)
            {
                AssemblyLoadResult result;
                try
                {
                    result = _assemblyLoader.LoadFromPath(resolvedReference.FilePath);
                }
                catch (FileNotFoundException e)
                {
                    Console.Error.WriteLine(e.Message);
                    return;
                }
                catch (ArgumentException e)
                {
                    Console.Error.WriteLine((e.InnerException ?? e).Message);
                    return;
                }
                catch (TargetInvocationException e)
                {
                    // The user might have hooked AssemblyResolve event, which might have thrown an exception.
                    // Display stack trace in this case.
                    Console.Error.WriteLine(e.InnerException.ToString());
                    return;
                }

                if (!result.IsSuccessful && !suppressWarnings)
                {
                    Console.Out.WriteLine(string.Format(CultureInfo.CurrentCulture, FeaturesResources.RequestedAssemblyAlreadyLoaded, result.OriginalPath));
                }
            }
Beispiel #48
0
 private static string GetReferenceKey(PortableExecutableReference reference)
 => reference.FilePath ?? reference.Display;
Beispiel #49
0
 public NamedMetadataReference(PortableExecutableReference reference, AssemblyNameReference name) => (Reference, Name) = (reference, name);
            public MetadataInfoCreator(
                Solution solution, VersionStamp version, PortableExecutableReference reference, CancellationToken cancellationToken)
            {
                _solution = solution;
                _version = version;
                _reference = reference;
                _cancellationToken = cancellationToken;
                _metadataReader = null;
                _allTypeDefinitions = new List<MetadataDefinition>();

                _inheritanceMap = OrderPreservingMultiDictionary<string, string>.GetInstance();
                _parentToChildren = OrderPreservingMultiDictionary<MetadataNode, MetadataNode>.GetInstance();
                _rootNode = MetadataNode.Allocate(name: "");
            }
            private async Task UpdateReferenceAsync(
                Project project, Compilation compilation, PortableExecutableReference reference, CancellationToken cancellationToken)
            {
                var key = GetReferenceKey(reference);
                if (key == null)
                {
                    return;
                }

                if (!TryGetLastWriteTime(key, out var lastWriteTime))
                {
                    // Couldn't get the write time.  Just ignore this reference.
                    return;
                }

                if (!_metadataPathToInfo.TryGetValue(key, out var metadataInfo) || metadataInfo.TimeStamp == lastWriteTime)
                {
                    var info = await SymbolTreeInfo.TryGetInfoForMetadataReferenceAsync(
                        project.Solution, reference, loadOnly: false, cancellationToken: cancellationToken).ConfigureAwait(false);

                    // Note, getting the info may fail (for example, bogus metadata).  That's ok.  
                    // We still want to cache that result so that don't try to continuously produce
                    // this info over and over again.
                    metadataInfo = new MetadataInfo(lastWriteTime, info, metadataInfo.ReferencingProjects ?? new HashSet<ProjectId>());
                    _metadataPathToInfo.AddOrUpdate(key, metadataInfo, (_1, _2) => metadataInfo);
                }

                // Keep track that this dll is referenced by this project.
                metadataInfo.ReferencingProjects.Add(project.Id);
            }
 /// <summary>
 /// We ignore references that are in a directory that contains the names "Packages".
 /// These directories are most likely the ones produced by NuGet, and we don't want
 /// to offer to add .dll reference manually for dlls that are part of NuGet packages.
 ///
 /// Note that this is only a heuristic (though a good one), and we should remove this
 /// when we can get an API from NuGet that tells us if a reference is actually provided
 /// by a nuget packages.
 ///
 /// This heuristic will do the right thing in practically all cases for all. It
 /// prevents the very unpleasant experience of us offering to add a direct metadata
 /// reference to something that should only be referenced as a nuget package.
 ///
 /// It does mean that if the following is true:
 /// You have a project that has a non-nuget metadata reference to something in a "packages"
 /// directory, and you are in another project that uses a type name that would have matched
 /// an accessible type from that dll. then we will not offer to add that .dll reference to
 /// that other project.
 ///
 /// However, that would be an exceedingly uncommon case that is degraded.  Whereas we're
 /// vastly improved in the common case. This is a totally acceptable and desirable outcome
 /// for such a heuristic.
 /// </summary>
 private bool IsInPackagesDirectory(PortableExecutableReference reference)
 {
     return(PathUtilities.ContainsPathComponent(reference.FilePath, "packages", ignoreCase: true));
 }
 private void WritePortableExecutableReferenceMetadataTo(
     PortableExecutableReference reference, ObjectWriter writer, CancellationToken cancellationToken)
 {
     var metadata = GetMetadata(reference);
     WriteTo(metadata, writer, cancellationToken);
 }
 bool IEqualityComparer <PortableExecutableReference> .Equals(PortableExecutableReference x, PortableExecutableReference y)
 {
     return(StringComparer.OrdinalIgnoreCase.Equals(
                x.FilePath ?? x.Display,
                y.FilePath ?? y.Display));
 }
            public async Task<SymbolTreeInfo> TryGetMetadataSymbolTreeInfoAsync(
                Solution solution,
                PortableExecutableReference reference,
                CancellationToken cancellationToken)
            {
                var key = GetReferenceKey(reference);
                if (key != null)
                {
                    MetadataInfo metadataInfo;
                    if (_metadataPathToInfo.TryGetValue(key, out metadataInfo))
                    {
                        DateTime writeTime;
                        if (TryGetLastWriteTime(key, out writeTime) && writeTime == metadataInfo.TimeStamp)
                        {
                            return metadataInfo.SymbolTreeInfo;
                        }
                    }
                }

                // If we didn't have it in our cache, see if we can load it from disk.
                // Note: pass 'loadOnly' so we only attempt to load from disk, not to actually
                // try to create the metadata.
                var info = await SymbolTreeInfo.GetInfoForMetadataReferenceAsync(
                    solution, reference, loadOnly: true, cancellationToken: cancellationToken).ConfigureAwait(false);
                return info;
            }
        private static async Task<SymbolTreeInfo> TryGetInfoForMetadataReferenceSlowAsync(
            Solution solution, PortableExecutableReference reference,
            bool loadOnly, Metadata metadata, CancellationToken cancellationToken)
        {
            // Find the lock associated with this piece of metadata.  This way only one thread is
            // computing a symbol tree info for a particular piece of metadata at a time.
            var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback);
            using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (s_metadataIdToInfo.TryGetValue(metadata.Id, out var infoTask))
                {
                    return await infoTask.ConfigureAwait(false);
                }

                var info = await LoadOrCreateMetadataSymbolTreeInfoAsync(
                    solution, reference, loadOnly, cancellationToken: cancellationToken).ConfigureAwait(false);
                if (info == null && loadOnly)
                {
                    return null;
                }

                // Cache the result in our dictionary.  Store it as a completed task so that 
                // future callers don't need to allocate to get the result back.
                infoTask = Task.FromResult(info);
                s_metadataIdToInfo.Add(metadata.Id, infoTask);

                return info;
            }
        }
Beispiel #57
0
 public static ModuleInstance Create(PortableExecutableReference reference)
 {
     // make a copy of the metadata, so that we don't dispose the metadata of a reference that are shared accross tests:
     return(Create(reference.GetMetadata(), symReader: null, includeLocalSignatures: false));
 }
 static Task GetNewTask(IncrementalAnalyzer self, Func <IncrementalAnalyzer, Project, PortableExecutableReference, CancellationToken, Task> func, Project project, PortableExecutableReference reference, CancellationToken cancellationToken)
 {
     return(Task.Run(() => func(self, project, reference, cancellationToken), cancellationToken));
 }