diff --git a/src/Workspaces/Core/Portable/Remote/RemoteArguments.cs b/src/Workspaces/Core/Portable/Remote/RemoteArguments.cs index 7ca3ced163be6..f6c6378b82147 100644 --- a/src/Workspaces/Core/Portable/Remote/RemoteArguments.cs +++ b/src/Workspaces/Core/Portable/Remote/RemoteArguments.cs @@ -107,14 +107,14 @@ public async Task TryRehydrateAsync( // The server and client should both be talking about the same compilation. As such // locations in symbols are save to resolve as we rehydrate the SymbolKey. var symbol = SymbolKey.ResolveString( - SymbolKeyData, compilation, cancellationToken: cancellationToken).GetAnySymbol(); + SymbolKeyData, compilation, out var failureReason, cancellationToken).GetAnySymbol(); if (symbol == null) { try { throw new InvalidOperationException( - $"We should always be able to resolve a symbol back on the host side:\r\n{SymbolKeyData}"); + $"We should always be able to resolve a symbol back on the host side:\r\n{SymbolKeyData}\r\n{failureReason}"); } catch (Exception ex) when (FatalError.ReportWithoutCrash(ex)) { diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AliasSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AliasSymbolKey.cs index 16c62ad938634..d4b6bd9caa68a 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AliasSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AliasSymbolKey.cs @@ -18,12 +18,18 @@ public static void Create(IAliasSymbol symbol, SymbolKeyWriter visitor) visitor.WriteString(FirstOrDefault(symbol.DeclaringSyntaxReferences)?.SyntaxTree.FilePath ?? ""); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var name = reader.ReadString(); - var targetResolution = reader.ReadSymbolKey(); + var targetResolution = reader.ReadSymbolKey(out var targetFailureReason); var filePath = reader.ReadString(); + if (targetFailureReason != null) + { + failureReason = $"({nameof(AliasSymbolKey)} {nameof(targetResolution)} failed -> {targetFailureReason})"; + return default; + } + var syntaxTree = reader.GetSyntaxTree(filePath); if (syntaxTree != null) { @@ -34,11 +40,13 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) var result = Resolve(semanticModel, syntaxTree.GetRoot(reader.CancellationToken), name, target, reader.CancellationToken); if (result.HasValue) { + failureReason = null; return result.Value; } } } + failureReason = $"({nameof(AliasSymbolKey)} '{name}' not found)"; return default; } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousFunctionOrDelegateSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousFunctionOrDelegateSymbolKey.cs index 9e37a9aad8a6c..f2fdae2dbaf9f 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousFunctionOrDelegateSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousFunctionOrDelegateSymbolKey.cs @@ -31,14 +31,21 @@ public static void Create(ISymbol symbol, SymbolKeyWriter visitor) visitor.WriteLocation(FirstOrDefault(symbol.Locations)); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var isAnonymousDelegateType = reader.ReadBoolean(); - var location = reader.ReadLocation(); + var location = reader.ReadLocation(out var locationFailureReason); + + if (locationFailureReason != null) + { + failureReason = $"({nameof(AnonymousFunctionOrDelegateSymbolKey)} {nameof(location)} failed -> {locationFailureReason})"; + return default; + } var syntaxTree = location.SourceTree; if (syntaxTree == null) { + failureReason = $"({nameof(AnonymousFunctionOrDelegateSymbolKey)} {nameof(SyntaxTree)} failed)"; return default; } @@ -58,6 +65,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) symbol = anonymousDelegate; } + failureReason = null; return new SymbolKeyResolution(symbol); } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousTypeSymbolKey.cs index 1482acb3cd495..b9408cc4565a1 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AnonymousTypeSymbolKey.cs @@ -28,12 +28,24 @@ public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) visitor.WriteLocationArray(propertyLocations); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { - using var propertyTypes = reader.ReadSymbolKeyArray(); + using var propertyTypes = reader.ReadSymbolKeyArray(out var propertyTypesFailureReason); using var propertyNames = reader.ReadStringArray(); using var propertyIsReadOnly = reader.ReadBooleanArray(); - using var propertyLocations = reader.ReadLocationArray(); + using var propertyLocations = reader.ReadLocationArray(out var propertyLocationsFailureReason); + + if (propertyTypesFailureReason != null) + { + failureReason = $"({nameof(AnonymousTypeSymbolKey)} {nameof(propertyTypes)} failed -> {propertyTypesFailureReason})"; + return default; + } + + if (propertyLocationsFailureReason != null) + { + failureReason = $"({nameof(AnonymousTypeSymbolKey)} {nameof(propertyLocations)} failed -> {propertyLocationsFailureReason})"; + return default; + } if (!propertyTypes.IsDefault) { @@ -42,6 +54,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) var anonymousType = reader.Compilation.CreateAnonymousTypeSymbol( propertyTypes.ToImmutable(), propertyNames.ToImmutable(), propertyIsReadOnly.ToImmutable(), propertyLocations.ToImmutable()); + failureReason = null; return new SymbolKeyResolution(anonymousType); } catch (ArgumentException) @@ -49,6 +62,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } + failureReason = null; return new SymbolKeyResolution(reader.Compilation.ObjectType); } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ArrayTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ArrayTypeSymbolKey.cs index 2cbbfa3dccbe3..28a9eab15747d 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ArrayTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ArrayTypeSymbolKey.cs @@ -14,18 +14,22 @@ public static void Create(IArrayTypeSymbol symbol, SymbolKeyWriter visitor) visitor.WriteInteger(symbol.Rank); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { - var elementTypeResolution = reader.ReadSymbolKey(); + var elementTypeResolution = reader.ReadSymbolKey(out var elementTypeFailureReason); var rank = reader.ReadInteger(); + if (elementTypeFailureReason != null) + { + failureReason = $"({nameof(ArrayTypeSymbolKey)} {nameof(elementTypeResolution)} failed -> {elementTypeFailureReason})"; + return default; + } + using var result = PooledArrayBuilder.GetInstance(elementTypeResolution.SymbolCount); foreach (var typeSymbol in elementTypeResolution.OfType()) - { result.AddIfNotNull(reader.Compilation.CreateArrayTypeSymbol(typeSymbol, rank)); - } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(ArrayTypeSymbolKey)})", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AssemblySymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AssemblySymbolKey.cs index 972480399850c..c86d0720bc2c7 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AssemblySymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.AssemblySymbolKey.cs @@ -17,7 +17,7 @@ public static void Create(IAssemblySymbol symbol, SymbolKeyWriter visitor) visitor.WriteString(symbol.Identity.Name); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var assemblyName = reader.ReadString(); var compilation = reader.Compilation; @@ -38,7 +38,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(AssemblySymbolKey)} '{assemblyName}' not found)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.BodyLevelSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.BodyLevelSymbolKey.cs index 4be5bdc419dda..1b662ffb0fdd4 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.BodyLevelSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.BodyLevelSymbolKey.cs @@ -116,15 +116,21 @@ private static bool TryGetSemanticModel( return false; } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string? failureReason) { var cancellationToken = reader.CancellationToken; var name = reader.ReadString(); var kind = (SymbolKind)reader.ReadInteger(); - var locations = reader.ReadLocationArray(); + var locations = reader.ReadLocationArray(out var locationsFailureReason); var ordinal = reader.ReadInteger(); + if (locationsFailureReason != null) + { + failureReason = $"({nameof(BodyLevelSymbolKey)} {nameof(locations)} failed -> {locationsFailureReason})"; + return default; + } + // First check if we can recover the symbol just through the original location. foreach (var loc in locations) { @@ -136,6 +142,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) if (symbol?.Kind == kind && SymbolKey.Equals(reader.Compilation, name, symbol.Name)) { + failureReason = null; return resolution; } } @@ -148,10 +155,14 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) foreach (var symbol in EnumerateSymbols(semanticModel, kind, name, cancellationToken)) { if (symbol.ordinal == ordinal) + { + failureReason = null; return new SymbolKeyResolution(symbol.symbol); + } } } + failureReason = $"({nameof(BodyLevelSymbolKey)} '{name}' not found)"; return default; } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.DynamicTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.DynamicTypeSymbolKey.cs index 8423b72ae372b..90a12bac68ff1 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.DynamicTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.DynamicTypeSymbolKey.cs @@ -14,8 +14,11 @@ public static void Create(SymbolKeyWriter _) // per compilation. } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) - => new SymbolKeyResolution(reader.Compilation.DynamicType); + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) + { + failureReason = null; + return new SymbolKeyResolution(reader.Compilation.DynamicType); + } } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ErrorTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ErrorTypeSymbolKey.cs index 387fe6987b81d..7db7c6f7b48a0 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ErrorTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ErrorTypeSymbolKey.cs @@ -57,15 +57,30 @@ private static ImmutableArray GetContainingNamespaceNamesInReverse(IName return builder.ToImmutable(); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var name = reader.ReadString(); - var containingSymbolResolution = ResolveContainer(reader); + + var containingSymbolResolution = ResolveContainer(reader, out var containingSymbolFailureReason); var arity = reader.ReadInteger(); - using var typeArguments = reader.ReadSymbolKeyArray(); + using var typeArguments = reader.ReadSymbolKeyArray(out var typeArgumentsFailureReason); + + if (containingSymbolFailureReason != null) + { + failureReason = $"({nameof(ErrorTypeSymbolKey)} {nameof(containingSymbolResolution)} failed -> {containingSymbolFailureReason})"; + return default; + } + + if (typeArgumentsFailureReason != null) + { + failureReason = $"({nameof(ErrorTypeSymbolKey)} {nameof(typeArguments)} failed -> {typeArgumentsFailureReason})"; + return default; + } + if (typeArguments.IsDefault) { + failureReason = $"({nameof(ErrorTypeSymbolKey)} {nameof(typeArguments)} failed)"; return default; } @@ -85,15 +100,15 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) reader, container: null, name, arity, typeArgumentsArray)); } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(ErrorTypeSymbolKey)} failed)", out failureReason); } - private static SymbolKeyResolution ResolveContainer(SymbolKeyReader reader) + private static SymbolKeyResolution ResolveContainer(SymbolKeyReader reader, out string failureReason) { var type = reader.ReadInteger(); if (type == 0) - return reader.ReadSymbolKey(); + return reader.ReadSymbolKey(out failureReason); if (type == 1) { @@ -104,11 +119,15 @@ private static SymbolKeyResolution ResolveContainer(SymbolKeyReader reader) for (var i = namespaceNames.Count - 1; i >= 0; i--) currentNamespace = reader.Compilation.CreateErrorNamespaceSymbol(currentNamespace, namespaceNames[i]); + failureReason = null; return new SymbolKeyResolution(currentNamespace); } if (type == 2) + { + failureReason = null; return default; + } throw ExceptionUtilities.UnexpectedValue(type); } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.EventSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.EventSymbolKey.cs index c7c9bbdf8a5e2..efffd875b6a1d 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.EventSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.EventSymbolKey.cs @@ -14,13 +14,19 @@ public static void Create(IEventSymbol symbol, SymbolKeyWriter visitor) visitor.WriteSymbolKey(symbol.ContainingType); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); - var containingTypeResolution = reader.ReadSymbolKey(); + var containingTypeResolution = reader.ReadSymbolKey(out var containingTypeFailureReason); + + if (containingTypeFailureReason != null) + { + failureReason = $"({nameof(EventSymbolKey)} {nameof(containingTypeResolution)} failed -> {containingTypeFailureReason})"; + return default; + } using var result = GetMembersOfNamedType(containingTypeResolution, metadataName); - return CreateResolution(result); + return CreateResolution(result, $"({nameof(EventSymbolKey)} '{metadataName}' not found)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FieldSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FieldSymbolKey.cs index 4e389d647b018..220e987cc90bb 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FieldSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FieldSymbolKey.cs @@ -14,13 +14,19 @@ public static void Create(IFieldSymbol symbol, SymbolKeyWriter visitor) visitor.WriteSymbolKey(symbol.ContainingType); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); - var containingTypeResolution = reader.ReadSymbolKey(); + var containingTypeResolution = reader.ReadSymbolKey(out var containingTypeFailureReason); + + if (containingTypeFailureReason != null) + { + failureReason = $"({nameof(FieldSymbolKey)} {nameof(containingTypeResolution)} failed -> {containingTypeFailureReason})"; + return default; + } using var result = GetMembersOfNamedType(containingTypeResolution, metadataName); - return CreateResolution(result); + return CreateResolution(result, $"({nameof(FieldSymbolKey)} '{metadataName}' not found)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FunctionPointerTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FunctionPointerTypeSymbolKey.cs index 31e9b64f12fc3..68d5eaa611535 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FunctionPointerTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.FunctionPointerTypeSymbolKey.cs @@ -16,20 +16,40 @@ public static void Create(IFunctionPointerTypeSymbol symbol, SymbolKeyWriter vis visitor.WriteParameterTypesArray(symbol.Signature.Parameters); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var returnRefKind = reader.ReadRefKind(); - var returnType = reader.ReadSymbolKey(); + var returnType = reader.ReadSymbolKey(out var returnTypeFailureReason); using var paramRefKinds = reader.ReadRefKindArray(); - using var paramTypes = reader.ReadSymbolKeyArray(); + using var parameterTypes = reader.ReadSymbolKeyArray(out var parameterTypesFailureReason); - if (paramTypes.IsDefault || !(returnType.GetAnySymbol() is ITypeSymbol returnTypeSymbol)) + if (returnTypeFailureReason != null) { + failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} {nameof(returnType)} failed -> {returnTypeFailureReason})"; return default; } + if (parameterTypesFailureReason != null) + { + failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} {nameof(parameterTypes)} failed -> {parameterTypesFailureReason})"; + return default; + } + + if (parameterTypes.IsDefault) + { + failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} no parameter types)"; + return default; + } + + if (!(returnType.GetAnySymbol() is ITypeSymbol returnTypeSymbol)) + { + failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} no return type)"; + return default; + } + + failureReason = null; return new SymbolKeyResolution(reader.Compilation.CreateFunctionPointerTypeSymbol( - returnTypeSymbol, returnRefKind, paramTypes.ToImmutable(), paramRefKinds.ToImmutable())); + returnTypeSymbol, returnRefKind, parameterTypes.ToImmutable(), paramRefKinds.ToImmutable())); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.MethodSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.MethodSymbolKey.cs index a8d1fc0906bc6..27446a85cea4c 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.MethodSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.MethodSymbolKey.cs @@ -18,10 +18,21 @@ public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor) visitor.WriteSymbolKey(symbol.ReceiverType); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { - var reducedFromResolution = reader.ReadSymbolKey(); - var receiverTypeResolution = reader.ReadSymbolKey(); + var reducedFromResolution = reader.ReadSymbolKey(out var reducedFromFailureReason); + if (reducedFromFailureReason != null) + { + failureReason = $"({nameof(ReducedExtensionMethodSymbolKey)} {nameof(reducedFromResolution)} failed -> {reducedFromFailureReason})"; + return default; + } + + var receiverTypeResolution = reader.ReadSymbolKey(out var receiverTypeFailureReason); + if (receiverTypeFailureReason != null) + { + failureReason = $"({nameof(ReducedExtensionMethodSymbolKey)} {nameof(receiverTypeResolution)} failed -> {receiverTypeFailureReason})"; + return default; + } using var result = PooledArrayBuilder.GetInstance(); foreach (var reducedFrom in reducedFromResolution.OfType()) @@ -32,7 +43,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(ReducedExtensionMethodSymbolKey)} failed)", out failureReason); } } } @@ -47,14 +58,25 @@ public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor) visitor.WriteSymbolKeyArray(symbol.TypeArguments); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { - var constructedFrom = reader.ReadSymbolKey(); - using var typeArguments = reader.ReadSymbolKeyArray(); + var constructedFrom = reader.ReadSymbolKey(out var constructedFromFailureReason); + if (constructedFromFailureReason != null) + { + failureReason = $"({nameof(ConstructedMethodSymbolKey)} {nameof(constructedFrom)} failed -> {constructedFromFailureReason})"; + return default; + } - if (constructedFrom.SymbolCount == 0 || - typeArguments.IsDefault) + using var typeArguments = reader.ReadSymbolKeyArray(out var typeArgumentsFailureReason); + if (typeArgumentsFailureReason != null) { + failureReason = $"({nameof(ConstructedMethodSymbolKey)} {nameof(typeArguments)} failed -> {typeArgumentsFailureReason})"; + return default; + } + + if (constructedFrom.SymbolCount == 0 || typeArguments.IsDefault) + { + failureReason = $"({nameof(ConstructedMethodSymbolKey)} {nameof(typeArguments)} failed -> 'constructedFrom.SymbolCount == 0 || typeArguments.IsDefault')"; return default; } @@ -69,7 +91,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(ConstructedMethodSymbolKey)} could not successfully construct)", out failureReason); } } } @@ -110,10 +132,11 @@ public static void Create(IMethodSymbol symbol, SymbolKeyWriter visitor) visitor.PopMethod(symbol); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); - var containingType = reader.ReadSymbolKey(); + + var containingType = reader.ReadSymbolKey(out var containingTypeFailureReason); var arity = reader.ReadInteger(); var isPartialMethodImplementationPart = reader.ReadBoolean(); using var parameterRefKinds = reader.ReadRefKindArray(); @@ -158,15 +181,21 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) // read out the values. We don't actually need to use them, but we have // to effectively read past them in the string. - using (reader.ReadSymbolKeyArray()) + using (reader.ReadSymbolKeyArray(out _)) { - _ = reader.ReadSymbolKey(); + _ = reader.ReadSymbolKey(out _); } reader.PopMethod(methodOpt: null); } - return CreateResolution(result); + if (containingTypeFailureReason != null) + { + failureReason = $"({nameof(MethodSymbolKey)} {nameof(containingType)} failed -> {containingTypeFailureReason})"; + return default; + } + + return CreateResolution(result, $"({nameof(MethodSymbolKey)} '{metadataName}' not found)", out failureReason); } private static IMethodSymbol Resolve( @@ -207,8 +236,8 @@ private static IMethodSymbol Resolve( private static IMethodSymbol Resolve( SymbolKeyReader reader, bool isPartialMethodImplementationPart, IMethodSymbol method) { - using var originalParameterTypes = reader.ReadSymbolKeyArray(); - var returnType = (ITypeSymbol)reader.ReadSymbolKey().GetAnySymbol(); + using var originalParameterTypes = reader.ReadSymbolKeyArray(out _); + var returnType = (ITypeSymbol)reader.ReadSymbolKey(out _).GetAnySymbol(); if (reader.ParameterTypesMatch(method.OriginalDefinition.Parameters, originalParameterTypes)) { diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ModuleSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ModuleSymbolKey.cs index 74275d638e13e..5bd01ebb70a3f 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ModuleSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ModuleSymbolKey.cs @@ -11,9 +11,15 @@ private static class ModuleSymbolKey public static void Create(IModuleSymbol symbol, SymbolKeyWriter visitor) => visitor.WriteSymbolKey(symbol.ContainingSymbol); - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { - var containingSymbolResolution = reader.ReadSymbolKey(); + var containingSymbolResolution = reader.ReadSymbolKey(out var containingSymbolFailureReason); + + if (containingSymbolFailureReason != null) + { + failureReason = $"({nameof(ModuleSymbolKey)} {nameof(containingSymbolResolution)} failed -> {containingSymbolFailureReason})"; + return default; + } using var result = PooledArrayBuilder.GetInstance(); foreach (var assembly in containingSymbolResolution.OfType()) @@ -23,7 +29,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) result.AddValuesIfNotNull(assembly.Modules); } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(ModuleSymbolKey)} failed)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamedTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamedTypeSymbolKey.cs index 75cbf7dfdc12c..4b94ebe15abc1 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamedTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamedTypeSymbolKey.cs @@ -28,16 +28,29 @@ public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) } } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); - var containingSymbolResolution = reader.ReadSymbolKey(); + var containingSymbolResolution = reader.ReadSymbolKey(out var containingSymbolFailureReason); var arity = reader.ReadInteger(); var isUnboundGenericType = reader.ReadBoolean(); - using var typeArguments = reader.ReadSymbolKeyArray(); + using var typeArguments = reader.ReadSymbolKeyArray(out var typeArgumentsFailureReason); + + if (containingSymbolFailureReason != null) + { + failureReason = $"({nameof(NamedTypeSymbolKey)} {nameof(containingSymbolFailureReason)} failed -> {containingSymbolFailureReason})"; + return default; + } + + if (typeArgumentsFailureReason != null) + { + failureReason = $"({nameof(NamedTypeSymbolKey)} {nameof(typeArguments)} failed -> {typeArgumentsFailureReason})"; + return default; + } if (typeArguments.IsDefault) { + failureReason = $"({nameof(NamedTypeSymbolKey)} {nameof(typeArguments)} failed)"; return default; } @@ -52,7 +65,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) isUnboundGenericType, typeArgumentArray); } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(NamedTypeSymbolKey)} failed)", out failureReason); } private static void Resolve( diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamespaceSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamespaceSymbolKey.cs index 22298b8835924..b3e0fbfc437f2 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamespaceSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.NamespaceSymbolKey.cs @@ -52,14 +52,21 @@ public static void Create(INamespaceSymbol symbol, SymbolKeyWriter visitor) } } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); var isCompilationGlobalNamespace = reader.ReadBoolean(); - var containingSymbolResolution = reader.ReadSymbolKey(); + var containingSymbolResolution = reader.ReadSymbolKey(out var containingSymbolFailureReason); + + if (containingSymbolFailureReason != null) + { + failureReason = $"({nameof(EventSymbolKey)} {nameof(containingSymbolResolution)} failed -> {containingSymbolFailureReason})"; + return default; + } if (isCompilationGlobalNamespace) { + failureReason = null; return new SymbolKeyResolution(reader.Compilation.GlobalNamespace); } @@ -88,7 +95,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(NamespaceSymbolKey)} '{metadataName}' not found)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ParameterSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ParameterSymbolKey.cs index 58cbb56dc7e04..bca5b85438580 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ParameterSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.ParameterSymbolKey.cs @@ -16,10 +16,16 @@ public static void Create(IParameterSymbol symbol, SymbolKeyWriter visitor) visitor.WriteSymbolKey(symbol.ContainingSymbol); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); - var containingSymbolResolution = reader.ReadSymbolKey(); + var containingSymbolResolution = reader.ReadSymbolKey(out var containingSymbolFailureReason); + + if (containingSymbolFailureReason != null) + { + failureReason = $"({nameof(ParameterSymbolKey)} {nameof(containingSymbolResolution)} failed -> {containingSymbolFailureReason})"; + return default; + } using var result = PooledArrayBuilder.GetInstance(); foreach (var container in containingSymbolResolution) @@ -55,7 +61,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(ParameterSymbolKey)} '{metadataName}' not found)", out failureReason); } private static void Resolve( diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PointerTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PointerTypeSymbolKey.cs index 28cbc7980e3b3..37a6e0339bce7 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PointerTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PointerTypeSymbolKey.cs @@ -11,9 +11,15 @@ private static class PointerTypeSymbolKey public static void Create(IPointerTypeSymbol symbol, SymbolKeyWriter visitor) => visitor.WriteSymbolKey(symbol.PointedAtType); - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { - var pointedAtTypeResolution = reader.ReadSymbolKey(); + var pointedAtTypeResolution = reader.ReadSymbolKey(out var pointedAtTypeFailureReason); + + if (pointedAtTypeFailureReason != null) + { + failureReason = $"({nameof(PointerTypeSymbolKey)} {nameof(pointedAtTypeResolution)} failed -> {pointedAtTypeFailureReason})"; + return default; + } using var result = PooledArrayBuilder.GetInstance(pointedAtTypeResolution.SymbolCount); foreach (var typeSymbol in pointedAtTypeResolution.OfType()) @@ -21,7 +27,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) result.AddIfNotNull(reader.Compilation.CreatePointerTypeSymbol(typeSymbol)); } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(PointerTypeSymbolKey)} could not resolve)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PropertySymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PropertySymbolKey.cs index a9e0306209664..757418e0d3f6a 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PropertySymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.PropertySymbolKey.cs @@ -17,17 +17,29 @@ public static void Create(IPropertySymbol symbol, SymbolKeyWriter visitor) visitor.WriteParameterTypesArray(symbol.OriginalDefinition.Parameters); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var metadataName = reader.ReadString(); - var containingTypeResolution = reader.ReadSymbolKey(); + var containingTypeResolution = reader.ReadSymbolKey(out var containingTypeFailureReason); var isIndexer = reader.ReadBoolean(); - using var refKinds = reader.ReadRefKindArray(); - using var parameterTypes = reader.ReadSymbolKeyArray(); + using var parameterTypes = reader.ReadSymbolKeyArray(out var parameterTypesFailureReason); + + if (containingTypeFailureReason != null) + { + failureReason = $"({nameof(PropertySymbolKey)} {nameof(containingTypeResolution)} failed -> {containingTypeFailureReason})"; + return default; + } + + if (parameterTypesFailureReason != null) + { + failureReason = $"({nameof(PropertySymbolKey)} {nameof(parameterTypes)} failed -> {parameterTypesFailureReason})"; + return default; + } if (parameterTypes.IsDefault) { + failureReason = $"({nameof(PropertySymbolKey)} no parameter types)"; return default; } @@ -45,7 +57,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(PropertySymbolKey)} '{metadataName}' not found)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs index 8459282621be1..41ebbdf20795f 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.SymbolKeyReader.cs @@ -25,9 +25,9 @@ private abstract class Reader : IDisposable protected const char SpaceChar = ' '; protected const char DoubleQuoteChar = '"'; - private readonly Func _readString; - private readonly Func _readBoolean; - private readonly Func _readRefKind; + private readonly ReadFunction _readString; + private readonly ReadFunction _readBoolean; + private readonly ReadFunction _readRefKind; protected string Data { get; private set; } public CancellationToken CancellationToken { get; private set; } @@ -104,14 +104,22 @@ protected char EatSpace() => Eat(SpaceChar); public bool ReadBoolean() + => ReadBoolean(out _); + + public bool ReadBoolean(out string failureReason) { + failureReason = null; var val = ReadInteger(); Debug.Assert(val == 0 || val == 1); return val == 1; } public TStringResult ReadString() + => ReadString(out _); + + public TStringResult ReadString(out string failureReason) { + failureReason = null; EatSpace(); return ReadStringNoSpace(); } @@ -164,15 +172,15 @@ private void EatDoubleQuote() => Eat(DoubleQuoteChar); public PooledArrayBuilder ReadStringArray() - => ReadArray(_readString); + => ReadArray(_readString, out _); public PooledArrayBuilder ReadBooleanArray() - => ReadArray(_readBoolean); + => ReadArray(_readBoolean, out _); public PooledArrayBuilder ReadRefKindArray() - => ReadArray(_readRefKind); + => ReadArray(_readRefKind, out _); - public PooledArrayBuilder ReadArray(Func readFunction) + public PooledArrayBuilder ReadArray(ReadFunction readFunction, out string failureReason) { var builder = PooledArrayBuilder.GetInstance(); EatSpace(); @@ -182,19 +190,33 @@ public PooledArrayBuilder ReadArray(Func readFunction) EatOpenParen(); Eat(SymbolKeyType.Array); + string totalFailureReason = null; var length = ReadInteger(); for (var i = 0; i < length; i++) { CancellationToken.ThrowIfCancellationRequested(); - builder.Builder.Add(readFunction()); + builder.Builder.Add(readFunction(out var elementFailureReason)); + + if (elementFailureReason != null) + { + var reason = $"element {i} failed {elementFailureReason}"; + totalFailureReason = totalFailureReason == null + ? $"({reason})" + : $"(totalFailureReason -> {reason})"; + } } EatCloseParen(); + failureReason = totalFailureReason; return builder; } public RefKind ReadRefKind() + => ReadRefKind(out _); + + public RefKind ReadRefKind(out string failureReason) { + failureReason = null; return (RefKind)ReadInteger(); } } @@ -267,13 +289,15 @@ protected override object CreateNullForString() => null; } + private delegate T ReadFunction(out string failureReason); + private class SymbolKeyReader : Reader { private static readonly ObjectPool s_readerPool = SharedPools.Default(); private readonly Dictionary _idToResult = new Dictionary(); - private readonly Func _readSymbolKey; - private readonly Func _readLocation; + private readonly ReadFunction _readSymbolKey; + private readonly ReadFunction _readLocation; public Compilation Compilation { get; private set; } public bool IgnoreAssemblyKey { get; private set; } @@ -379,7 +403,7 @@ internal SyntaxTree GetSyntaxTree(string filePath) #region Symbols - public SymbolKeyResolution ReadSymbolKey() + public SymbolKeyResolution ReadSymbolKey(out string failureReason) { CancellationToken.ThrowIfCancellationRequested(); EatSpace(); @@ -388,6 +412,7 @@ public SymbolKeyResolution ReadSymbolKey() if (type == SymbolKeyType.Null) { Eat(type); + failureReason = null; return default; } @@ -401,10 +426,11 @@ public SymbolKeyResolution ReadSymbolKey() { var id = ReadInteger(); result = _idToResult[id]; + failureReason = null; } else { - result = ReadWorker(type); + result = ReadWorker(type, out failureReason); var id = ReadInteger(); _idToResult[id] = result; } @@ -414,32 +440,32 @@ public SymbolKeyResolution ReadSymbolKey() return result; } - private SymbolKeyResolution ReadWorker(SymbolKeyType type) + private SymbolKeyResolution ReadWorker(SymbolKeyType type, out string failureReason) => type switch { - SymbolKeyType.Alias => AliasSymbolKey.Resolve(this), - SymbolKeyType.BodyLevel => BodyLevelSymbolKey.Resolve(this), - SymbolKeyType.ConstructedMethod => ConstructedMethodSymbolKey.Resolve(this), - SymbolKeyType.NamedType => NamedTypeSymbolKey.Resolve(this), - SymbolKeyType.ErrorType => ErrorTypeSymbolKey.Resolve(this), - SymbolKeyType.Field => FieldSymbolKey.Resolve(this), - SymbolKeyType.FunctionPointer => FunctionPointerTypeSymbolKey.Resolve(this), - SymbolKeyType.DynamicType => DynamicTypeSymbolKey.Resolve(this), - SymbolKeyType.Method => MethodSymbolKey.Resolve(this), - SymbolKeyType.Namespace => NamespaceSymbolKey.Resolve(this), - SymbolKeyType.PointerType => PointerTypeSymbolKey.Resolve(this), - SymbolKeyType.Parameter => ParameterSymbolKey.Resolve(this), - SymbolKeyType.Property => PropertySymbolKey.Resolve(this), - SymbolKeyType.ArrayType => ArrayTypeSymbolKey.Resolve(this), - SymbolKeyType.Assembly => AssemblySymbolKey.Resolve(this), - SymbolKeyType.TupleType => TupleTypeSymbolKey.Resolve(this), - SymbolKeyType.Module => ModuleSymbolKey.Resolve(this), - SymbolKeyType.Event => EventSymbolKey.Resolve(this), - SymbolKeyType.ReducedExtensionMethod => ReducedExtensionMethodSymbolKey.Resolve(this), - SymbolKeyType.TypeParameter => TypeParameterSymbolKey.Resolve(this), - SymbolKeyType.AnonymousType => AnonymousTypeSymbolKey.Resolve(this), - SymbolKeyType.AnonymousFunctionOrDelegate => AnonymousFunctionOrDelegateSymbolKey.Resolve(this), - SymbolKeyType.TypeParameterOrdinal => TypeParameterOrdinalSymbolKey.Resolve(this), + SymbolKeyType.Alias => AliasSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.BodyLevel => BodyLevelSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.ConstructedMethod => ConstructedMethodSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.NamedType => NamedTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.ErrorType => ErrorTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Field => FieldSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.FunctionPointer => FunctionPointerTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.DynamicType => DynamicTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Method => MethodSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Namespace => NamespaceSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.PointerType => PointerTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Parameter => ParameterSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Property => PropertySymbolKey.Resolve(this, out failureReason), + SymbolKeyType.ArrayType => ArrayTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Assembly => AssemblySymbolKey.Resolve(this, out failureReason), + SymbolKeyType.TupleType => TupleTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Module => ModuleSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.Event => EventSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.ReducedExtensionMethod => ReducedExtensionMethodSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.TypeParameter => TypeParameterSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.AnonymousType => AnonymousTypeSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.AnonymousFunctionOrDelegate => AnonymousFunctionOrDelegateSymbolKey.Resolve(this, out failureReason), + SymbolKeyType.TypeParameterOrdinal => TypeParameterOrdinalSymbolKey.Resolve(this, out failureReason), _ => throw new NotImplementedException(), }; @@ -453,9 +479,14 @@ private SymbolKeyResolution ReadWorker(SymbolKeyType type) /// Callers should the instance returned. No check is /// necessary if default was returned before calling /// - public PooledArrayBuilder ReadSymbolKeyArray() where TSymbol : ISymbol + public PooledArrayBuilder ReadSymbolKeyArray(out string failureReason) where TSymbol : ISymbol { - using var resolutions = ReadArray(_readSymbolKey); + using var resolutions = ReadArray(_readSymbolKey, out var elementsFailureReason); + if (elementsFailureReason != null) + { + failureReason = elementsFailureReason; + return default; + } var result = PooledArrayBuilder.GetInstance(); foreach (var resolution in resolutions) @@ -467,10 +498,12 @@ public PooledArrayBuilder ReadSymbolKeyArray() where TSymbol : else { result.Dispose(); + failureReason = $"({nameof(ReadSymbolKeyArray)} incorrect type for element)"; return default; } } + failureReason = null; return result; } @@ -494,12 +527,13 @@ protected override string CreateNullForString() #region Locations - public Location ReadLocation() + public Location ReadLocation(out string failureReason) { EatSpace(); if ((SymbolKeyType)Data[Position] == SymbolKeyType.Null) { Eat(SymbolKeyType.Null); + failureReason = null; return null; } @@ -515,14 +549,21 @@ public Location ReadLocation() var syntaxTree = GetSyntaxTree(filePath); if (syntaxTree != null) { + failureReason = null; return Location.Create(syntaxTree, new TextSpan(start, length)); } } else if (kind == LocationKind.MetadataFile) { - var assemblyResolution = ReadSymbolKey(); + var assemblyResolution = ReadSymbolKey(out var assemblyFailureReason); var moduleName = ReadString(); + if (assemblyFailureReason != null) + { + failureReason = $"{nameof(ReadLocation)} {nameof(assemblyResolution)} failed -> " + assemblyFailureReason; + return Location.None; + } + // We may be resolving in a compilation where we don't have a module // with this name. In that case, just map this location to none. if (assemblyResolution.GetAnySymbol() is IAssemblySymbol assembly) @@ -533,12 +574,14 @@ public Location ReadLocation() var location = FirstOrDefault(module.Locations); if (location != null) { + failureReason = null; return location; } } } } + failureReason = null; return Location.None; } @@ -576,8 +619,8 @@ private static IModuleSymbol GetModule(IEnumerable modules, strin return null; } - public PooledArrayBuilder ReadLocationArray() - => ReadArray(_readLocation); + public PooledArrayBuilder ReadLocationArray(out string failureReason) + => ReadArray(_readLocation, out failureReason); #endregion } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TupleTypeSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TupleTypeSymbolKey.cs index cb2557af71a76..66089b79ec865 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TupleTypeSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TupleTypeSymbolKey.cs @@ -17,11 +17,20 @@ public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { Debug.Assert(symbol.IsTupleType); + var isError = symbol.TupleUnderlyingType.TypeKind == TypeKind.Error; + var friendlyNames = ArrayBuilder.GetInstance(); var locations = ArrayBuilder.GetInstance(); - var isError = symbol.TupleUnderlyingType.TypeKind == TypeKind.Error; + foreach (var element in symbol.TupleElements) + { + friendlyNames.Add(element.IsImplicitlyDeclared ? null : element.Name); + locations.Add(FirstOrDefault(element.Locations) ?? Location.None); + } + visitor.WriteBoolean(isError); + visitor.WriteStringArray(friendlyNames.ToImmutableAndFree()); + visitor.WriteLocationArray(locations.ToImmutableAndFree()); if (isError) { @@ -38,76 +47,79 @@ public static void Create(INamedTypeSymbol symbol, SymbolKeyWriter visitor) { visitor.WriteSymbolKey(symbol.TupleUnderlyingType); } + } - foreach (var element in symbol.TupleElements) - { - friendlyNames.Add(element.IsImplicitlyDeclared ? null : element.Name); - locations.Add(FirstOrDefault(element.Locations) ?? Location.None); - } + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) + { + var isError = reader.ReadBoolean(); - visitor.WriteStringArray(friendlyNames.ToImmutableAndFree()); - visitor.WriteLocationArray(locations.ToImmutableAndFree()); + return isError ? ResolveErrorTuple(reader, out failureReason) : ResolveNormalTuple(reader, out failureReason); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + private static SymbolKeyResolution ResolveNormalTuple(SymbolKeyReader reader, out string failureReason) { - var isError = reader.ReadBoolean(); - if (isError) - { - using var elementTypes = reader.ReadSymbolKeyArray(); - using var elementNames = reader.ReadStringArray(); - var elementLocations = ReadElementLocations(reader); + using var elementNames = reader.ReadStringArray(); + var elementLocations = ReadElementLocations(reader, out var elementLocationsFailureReason); + var underlyingTypeResolution = reader.ReadSymbolKey(out var underlyingTypeFailureReason); - if (!elementTypes.IsDefault) - { - try - { - var result = reader.Compilation.CreateTupleTypeSymbol( - elementTypes.ToImmutable(), elementNames.ToImmutable(), elementLocations); - return new SymbolKeyResolution(result); - } - catch (ArgumentException) - { - } - } + if (underlyingTypeFailureReason != null) + { + failureReason = $"({nameof(TupleTypeSymbolKey)} {nameof(underlyingTypeResolution)} failed -> {underlyingTypeFailureReason})"; + return default; } - else + + using var result = PooledArrayBuilder.GetInstance(); + + var elementNamesArray = elementNames.ToImmutable(); + foreach (var namedType in underlyingTypeResolution.OfType()) { - var underlyingTypeResolution = reader.ReadSymbolKey(); - using var elementNamesBuilder = reader.ReadStringArray(); - var elementLocations = ReadElementLocations(reader); + result.AddIfNotNull(reader.Compilation.CreateTupleTypeSymbol( + namedType, elementNamesArray, elementLocations)); + } - try - { - using var result = PooledArrayBuilder.GetInstance(); + return CreateResolution(result, $"({nameof(TupleTypeSymbolKey)} failed)", out failureReason); + } - var elementNames = elementNamesBuilder.ToImmutable(); - foreach (var namedType in underlyingTypeResolution.OfType()) - { - result.AddIfNotNull(reader.Compilation.CreateTupleTypeSymbol( - namedType, elementNames, elementLocations)); - } + private static SymbolKeyResolution ResolveErrorTuple(SymbolKeyReader reader, out string failureReason) + { + using var elementNames = reader.ReadStringArray(); + var elementLocations = ReadElementLocations(reader, out var elementLocationsFailureReason); + using var elementTypes = reader.ReadSymbolKeyArray(out var elementTypesFailureReason); - return CreateResolution(result); - } - catch (ArgumentException) - { - } + if (elementLocationsFailureReason != null) + { + failureReason = $"({nameof(TupleTypeSymbolKey)} {nameof(elementLocations)} failed -> {elementLocationsFailureReason})"; + return default; + } + + if (elementTypesFailureReason != null) + { + failureReason = $"({nameof(TupleTypeSymbolKey)} {nameof(elementTypes)} failed -> {elementTypesFailureReason})"; + return default; + } + + if (elementTypes.IsDefault) + { + failureReason = $"({nameof(TupleTypeSymbolKey)} {nameof(elementTypes)} failed)"; + return default; } - return new SymbolKeyResolution(reader.Compilation.ObjectType); + var result = reader.Compilation.CreateTupleTypeSymbol( + elementTypes.ToImmutable(), elementNames.ToImmutable(), elementLocations); + failureReason = null; + return new SymbolKeyResolution(result); } - private static ImmutableArray ReadElementLocations(SymbolKeyReader reader) + private static ImmutableArray ReadElementLocations(SymbolKeyReader reader, out string failureReason) { - using var elementLocations = reader.ReadLocationArray(); + using var elementLocations = reader.ReadLocationArray(out failureReason); + if (failureReason != null) + return default; // Compiler API requires that all the locations are non-null, or that there is a default // immutable array passed in. if (elementLocations.Builder.All(loc => loc == null)) - { return default; - } return elementLocations.ToImmutable(); } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterOrdinalSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterOrdinalSymbolKey.cs index cd422fb78d0c6..f1d5c470ec03c 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterOrdinalSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterOrdinalSymbolKey.cs @@ -17,15 +17,21 @@ public static void Create(ITypeParameterSymbol symbol, int methodIndex, SymbolKe visitor.WriteInteger(symbol.Ordinal); } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var methodIndex = reader.ReadInteger(); var ordinal = reader.ReadInteger(); var method = reader.ResolveMethod(methodIndex); + var typeParameter = method?.TypeParameters[ordinal]; - return typeParameter == null - ? default - : new SymbolKeyResolution(typeParameter); + if (typeParameter == null) + { + failureReason = $"({nameof(TypeParameterOrdinalSymbolKey)} failed)"; + return default; + } + + failureReason = null; + return new SymbolKeyResolution(typeParameter); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterSymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterSymbolKey.cs index ef2cf73383080..fcafa1134af87 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterSymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.TypeParameterSymbolKey.cs @@ -25,20 +25,34 @@ public static void Create(ITypeParameterSymbol symbol, SymbolKeyWriter visitor) } } - public static SymbolKeyResolution Resolve(SymbolKeyReader reader) + public static SymbolKeyResolution Resolve(SymbolKeyReader reader, out string failureReason) { var isCref = reader.ReadBoolean(); if (isCref) { - var location = reader.ReadLocation(); + var location = reader.ReadLocation(out var locationFailureReason); + if (locationFailureReason != null) + { + failureReason = $"({nameof(TypeParameterSymbolKey)} {nameof(location)} failed -> {locationFailureReason})"; + return default; + } + var resolution = reader.ResolveLocation(location); + + failureReason = null; return resolution.GetValueOrDefault(); } else { var metadataName = reader.ReadString(); - var containingSymbolResolution = reader.ReadSymbolKey(); + var containingSymbolResolution = reader.ReadSymbolKey(out var containingSymbolFailureReason); + + if (containingSymbolFailureReason != null) + { + failureReason = $"({nameof(TypeParameterSymbolKey)} {nameof(containingSymbolResolution)} failed -> {containingSymbolFailureReason})"; + return default; + } using var result = PooledArrayBuilder.GetInstance(); foreach (var containingSymbol in containingSymbolResolution) @@ -52,7 +66,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader) } } - return CreateResolution(result); + return CreateResolution(result, $"({nameof(TypeParameterSymbolKey)} '{metadataName}' not found)", out failureReason); } } } diff --git a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs index b558e880cc728..af4bca827b1ba 100644 --- a/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs +++ b/src/Workspaces/Core/Portable/SymbolKey/SymbolKey.cs @@ -160,16 +160,31 @@ public static bool CanCreate(ISymbol symbol, CancellationToken cancellationToken public static SymbolKeyResolution ResolveString( string symbolKey, Compilation compilation, bool ignoreAssemblyKey = false, CancellationToken cancellationToken = default) + { + return ResolveString(symbolKey, compilation, ignoreAssemblyKey, out _, cancellationToken); + } + + public static SymbolKeyResolution ResolveString( + string symbolKey, Compilation compilation, + out string failureReason, CancellationToken cancellationToken) + { + return ResolveString(symbolKey, compilation, ignoreAssemblyKey: false, out failureReason, cancellationToken); + } + + public static SymbolKeyResolution ResolveString( + string symbolKey, Compilation compilation, bool ignoreAssemblyKey, + out string failureReason, CancellationToken cancellationToken) { using var reader = SymbolKeyReader.GetReader( symbolKey, compilation, ignoreAssemblyKey, cancellationToken); var version = reader.ReadFormatVersion(); if (version != FormatVersion) { + failureReason = $"({nameof(SymbolKey)} invalid format '${version}')"; return default; } - var result = reader.ReadSymbolKey(); + var result = reader.ReadSymbolKey(out failureReason); Debug.Assert(reader.Position == symbolKey.Length); return result; } @@ -208,7 +223,8 @@ public SymbolKeyResolution Resolve( public override string ToString() => _symbolKeyData; - private static SymbolKeyResolution CreateResolution(PooledArrayBuilder symbols) + private static SymbolKeyResolution CreateResolution( + PooledArrayBuilder symbols, string reasonIfFailed, out string failureReason) where TSymbol : class, ISymbol { #if DEBUG @@ -220,14 +236,17 @@ private static SymbolKeyResolution CreateResolution(PooledArrayBuilder< if (symbols.Builder.Count == 0) { + failureReason = reasonIfFailed; return default; } else if (symbols.Builder.Count == 1) { + failureReason = null; return new SymbolKeyResolution(symbols.Builder[0]); } else { + failureReason = null; return new SymbolKeyResolution( ImmutableArray.CastUp(symbols.Builder.ToImmutable()), CandidateReason.Ambiguous);