diff --git a/src/Compilers/Core/Portable/MetadataReference/PortableExecutableReference.cs b/src/Compilers/Core/Portable/MetadataReference/PortableExecutableReference.cs index 195e2066b764bfe2f9b19b57ef1393bb4938e851..4415ee739daa2d8d9b596c76368d152b1f0b1991 100644 --- a/src/Compilers/Core/Portable/MetadataReference/PortableExecutableReference.cs +++ b/src/Compilers/Core/Portable/MetadataReference/PortableExecutableReference.cs @@ -170,6 +170,19 @@ public Metadata GetMetadata() return GetMetadataNoCopy().Copy(); } + /// + /// Returns the for this reference's . + /// This will be equivalent to calling ., + /// but can be done more efficiently. + /// + /// If the PE image format is invalid. + /// The metadata image content can't be read. + /// The metadata image is stored in a file that can't be found. + public MetadataId GetMetadataId() + { + return GetMetadataNoCopy().Id; + } + internal static Diagnostic ExceptionToDiagnostic(Exception e, CommonMessageProvider messageProvider, Location location, string display, MetadataImageKind kind) { if (e is BadImageFormatException) diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index c60d90ec24decff01bac16e0075096faac4cdb98..bcea505028bec2fa1cd3aaf3502a1e1ab1e27658 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -175,6 +175,7 @@ Microsoft.CodeAnalysis.OperationKind.VariableDeclarationStatement = 3 -> Microso Microsoft.CodeAnalysis.OperationKind.WithStatement = 82 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.YieldBreakStatement = 12 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.YieldReturnStatement = 16 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.PortableExecutableReference.GetMetadataId() -> Microsoft.CodeAnalysis.MetadataId Microsoft.CodeAnalysis.SemanticModel.GetOperation(Microsoft.CodeAnalysis.SyntaxNode node, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ArgumentKind Microsoft.CodeAnalysis.Semantics.ArgumentKind.DefaultValue = 4 -> Microsoft.CodeAnalysis.Semantics.ArgumentKind diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs index d3228829fd37ec55faa75d2735e11c9a5789aed8..a4384ffac6a2cc69940e4372c8703a42d3dc6bdb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs @@ -54,6 +54,18 @@ private static int IndexOfCharacter(BlobReader blobReader, char ch) } } + private static MetadataId GetMetadataIdNoThrow(PortableExecutableReference reference) + { + try + { + return reference.GetMetadataId(); + } + catch (Exception e) when (e is BadImageFormatException || e is IOException) + { + return null; + } + } + private static Metadata GetMetadataNoThrow(PortableExecutableReference reference) { try @@ -77,8 +89,8 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference bool loadOnly, CancellationToken cancellationToken) { - var metadata = GetMetadataNoThrow(reference); - if (metadata == null) + var metadataId = GetMetadataIdNoThrow(reference); + if (metadataId == null) { return SpecializedTasks.Default(); } @@ -87,12 +99,17 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference // 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). - Task infoTask; - if (s_metadataIdToInfo.TryGetValue(metadata.Id, out infoTask)) + if (s_metadataIdToInfo.TryGetValue(metadataId, out var infoTask)) { return infoTask; } + var metadata = GetMetadataNoThrow(reference); + if (metadata == null) + { + return SpecializedTasks.Default(); + } + return TryGetInfoForMetadataReferenceSlowAsync( solution, reference, loadOnly, metadata, cancellationToken); } @@ -107,9 +124,7 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); - - Task infoTask; - if (s_metadataIdToInfo.TryGetValue(metadata.Id, out infoTask)) + if (s_metadataIdToInfo.TryGetValue(metadata.Id, out var infoTask)) { return await infoTask.ConfigureAwait(false); } @@ -693,11 +708,9 @@ public MetadataDefinition(MetadataDefinitionKind kind, string name) public static MetadataDefinition Create( MetadataReader reader, TypeDefinition definition) { - string typeName = GetMetadataNameWithoutBackticks(reader, definition.Name); + var typeName = GetMetadataNameWithoutBackticks(reader, definition.Name); - return new MetadataDefinition( - MetadataDefinitionKind.Type, - typeName) + return new MetadataDefinition(MetadataDefinitionKind.Type,typeName) { Type = definition };