private MetadataShadowCopy GetMetadataShadowCopyNoCheck(string fullPath, MetadataImageKind kind) { if (kind < MetadataImageKind.Assembly || kind > MetadataImageKind.Module) { throw new ArgumentOutOfRangeException("kind"); } FileKey key = FileKey.Create(fullPath); lock (Guard) { CacheEntry <MetadataShadowCopy> existing; if (CopyExistsOrIsSuppressed(key, out existing)) { return(existing.Public); } } CacheEntry <MetadataShadowCopy> newCopy = CreateMetadataShadowCopy(fullPath, kind); // last-write timestamp is copied from the original file at the time the snapshot was made: bool fault = true; try { key = new FileKey(fullPath, FileUtilities.GetLastWriteTimeStamp(newCopy.Public.PrimaryModule.FullPath)); fault = false; } finally { if (fault) { newCopy.Private.Dispose(); } } lock (Guard) { CacheEntry <MetadataShadowCopy> existing; if (CopyExistsOrIsSuppressed(key, out existing)) { newCopy.Private.Dispose(); return(existing.Public); } _shadowCopies.Add(key, newCopy); } return(newCopy.Public); }
/// <summary> /// Gets or creates metadata for specified file path. /// </summary> /// <param name="fullPath">Full path to an assembly manifest module file or a standalone module file.</param> /// <param name="kind">Metadata kind (assembly or module).</param> /// <returns>Metadata for the specified file.</returns> /// <exception cref="IOException">Error reading file <paramref name="fullPath"/>. See <see cref="Exception.InnerException"/> for details.</exception> public Metadata GetMetadata(string fullPath, MetadataImageKind kind) { if (NeedsShadowCopy(fullPath)) { return(GetMetadataShadowCopyNoCheck(fullPath, kind).Metadata); } FileKey key = FileKey.Create(fullPath); lock (Guard) { CacheEntry <Metadata> existing; if (_noShadowCopyCache.TryGetValue(key, out existing)) { return(existing.Public); } } Metadata newMetadata; if (kind == MetadataImageKind.Assembly) { newMetadata = AssemblyMetadata.CreateFromFile(fullPath); } else { newMetadata = ModuleMetadata.CreateFromFile(fullPath); } // the files are locked (memory mapped) now key = FileKey.Create(fullPath); lock (Guard) { CacheEntry <Metadata> existing; if (_noShadowCopyCache.TryGetValue(key, out existing)) { newMetadata.Dispose(); return(existing.Public); } Metadata publicMetadata = newMetadata.Copy(); _noShadowCopyCache.Add(key, new CacheEntry <Metadata>(publicMetadata, newMetadata)); return(publicMetadata); } }
/// <exception cref="IOException"/> private static ModuleMetadata GetOrCreateModuleFromFile(string fullPath) { ModuleMetadata module = null; // may throw FileKey key = FileKey.Create(fullPath); CachedModule cachedModule; bool existingKey = modulesFromFiles.TryGetValue(key, out cachedModule); if (existingKey && cachedModule.Metadata.TryGetTarget(out module)) { return(module); } // mempy-map the module: module = ModuleMetadata.CreateFromFile(fullPath); // refresh the timestamp (the file may have changed just before we memory-mapped it): bool fault = true; try { key = FileKey.Create(fullPath); fault = false; } finally { if (fault) { module.Dispose(); } } cachedModule = new CachedModule(module); modulesFromFiles[key] = cachedModule; if (!existingKey) { moduleKeys.Add(key); EnableCompactTimer(); } return(module); }
/// <exception cref="IOException"/> private static AssemblyMetadata GetOrCreateAssemblyFromFile(string fullPath) { AssemblyMetadata assembly = null; // may throw: FileKey key = FileKey.Create(fullPath); CachedAssembly cachedAssembly; bool existingKey = assembliesFromFiles.TryGetValue(key, out cachedAssembly); if (existingKey && cachedAssembly.Metadata.TryGetTarget(out assembly)) { return(assembly); } // memory-map all modules of the assembly: assembly = AssemblyMetadata.CreateFromFile(fullPath); // refresh the timestamp (the file may have changed just before we memory-mapped it): bool fault = true; try { key = FileKey.Create(fullPath); fault = false; } finally { if (fault) { assembly.Dispose(); } } cachedAssembly = new CachedAssembly(assembly); assembliesFromFiles[key] = cachedAssembly; if (!existingKey) { assemblyKeys.Add(key); EnableCompactTimer(); } return(assembly); }
internal static ImmutableArray <DiagnosticAnalyzer> GetOrCreateAnalyzersFromFile(AnalyzerFileReference analyzerReference, string langauge = null) { string fullPath = analyzerReference.FullPath; Debug.Assert(PathUtilities.IsAbsolute(fullPath)); lock (Guard) { // may throw: FileKey key = FileKey.Create(fullPath); CachedAnalyzers cachedAnalyzers; if (analyzersFromFiles.TryGetValue(key, out cachedAnalyzers)) { if (cachedAnalyzers.Analyzers.IsAlive && cachedAnalyzers.Language == langauge) { return((ImmutableArray <DiagnosticAnalyzer>)cachedAnalyzers.Analyzers.Target); } else { analyzersFromFiles.Remove(key); var removed = analyzerAssemblyKeys.Remove(key); Debug.Assert(removed); Debug.Assert(!analyzerAssemblyKeys.Contains(key)); } } // get all analyzers in the assembly: var builder = ImmutableArray.CreateBuilder <DiagnosticAnalyzer>(); analyzerReference.AddAnalyzers(builder, langauge); var analyzers = builder.ToImmutable(); // refresh the timestamp (the file may have changed just before we memory-mapped it): key = FileKey.Create(fullPath); analyzersFromFiles[key] = new CachedAnalyzers(analyzers, langauge); Debug.Assert(!analyzerAssemblyKeys.Contains(key)); analyzerAssemblyKeys.Add(key); EnableCompactTimer(); return(analyzers); } }
private MetadataShadowCopy GetMetadataShadowCopyNoCheck(string fullPath, MetadataImageKind kind) { if (!kind.IsValid()) { throw new ArgumentOutOfRangeException("kind"); } FileKey key = new FileKey(fullPath); lock (Guard) { CacheEntry <MetadataShadowCopy> existing; if (CopyExistsOrIsSuppressed(key, out existing)) { return(existing.Public); } } CacheEntry <MetadataShadowCopy> newCopy = CreateMetadataShadowCopy(fullPath, kind); // last-write timestamp is copied from the original file at the time the snapshot was made: key = new FileKey(fullPath, FileKey.GetTimeStamp(newCopy.Public.PrimaryModule.FullPath)); lock (Guard) { CacheEntry <MetadataShadowCopy> existing; if (CopyExistsOrIsSuppressed(key, out existing)) { newCopy.Private.Dispose(); return(existing.Public); } shadowCopies.Add(key, newCopy); } return(newCopy.Public); }