private static void GetConstants(
            ArrayBuilder <TLocalSymbol> builder,
            EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider,
            ArrayBuilder <ISymUnmanagedScope> scopes,
            ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMapOpt,
            ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > tupleLocalConstantMapOpt)
        {
            foreach (var scope in scopes)
            {
                foreach (var constant in scope.GetConstants())
                {
                    string name      = constant.GetName();
                    object rawValue  = constant.GetValue();
                    var    signature = constant.GetSignature().ToImmutableArray();

                    TTypeSymbol type;
                    try
                    {
                        type = symbolProvider.DecodeLocalVariableType(signature);
                    }
                    catch (Exception e) when(e is UnsupportedSignatureContent || e is BadImageFormatException)
                    {
                        // ignore
                        continue;
                    }

                    if (type.Kind == SymbolKind.ErrorType)
                    {
                        continue;
                    }

                    ConstantValue constantValue = PdbHelpers.GetSymConstantValue(type, rawValue);

                    // TODO (https://github.com/dotnet/roslyn/issues/1815): report error properly when the symbol is used
                    if (constantValue.IsBad)
                    {
                        continue;
                    }

                    var dynamicFlags = default(ImmutableArray <bool>);
                    if (dynamicLocalConstantMapOpt != null)
                    {
                        dynamicLocalConstantMapOpt.TryGetValue(name, out dynamicFlags);
                    }

                    var tupleElementNames = default(ImmutableArray <string>);
                    if (tupleLocalConstantMapOpt != null)
                    {
                        int scopeStart = scope.GetStartOffset();
                        int scopeEnd   = scope.GetEndOffset();
                        tupleLocalConstantMapOpt.TryGetValue(new LocalNameAndScope(name, scopeStart, scopeEnd), out tupleElementNames);
                    }

                    builder.Add(symbolProvider.GetLocalConstant(name, type, constantValue, dynamicFlags, tupleElementNames));
                }
            }
        }
Esempio n. 2
0
        private static void ReadLocalScopeInformation(
            MetadataReader reader,
            MethodDefinitionHandle methodHandle,
            int ilOffset,
            EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider,
            bool isVisualBasicMethod,
            out ImmutableArray <ImmutableArray <ImportRecord> > importGroups,
            out ImmutableArray <ExternAliasRecord> externAliases,
            out ImmutableArray <string> localVariableNames,
            out ImmutableDictionary <int, ImmutableArray <bool> >?dynamicLocalMap,
            out ImmutableDictionary <int, ImmutableArray <string?> >?tupleLocalMap,
            out ImmutableArray <TLocalSymbol> localConstants,
            out ILSpan reuseSpan
            )
        {
            var localVariableNamesBuilder = ArrayBuilder <string> .GetInstance();

            var localConstantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance();

            ImmutableDictionary <int, ImmutableArray <bool> > .Builder?   lazyDynamicLocalsBuilder = null;
            ImmutableDictionary <int, ImmutableArray <string?> > .Builder?lazyTupleLocalsBuilder   =
                null;

            var  innerMostImportScope = default(ImportScopeHandle);
            uint reuseSpanStart       = 0;
            uint reuseSpanEnd         = uint.MaxValue;

            try
            {
                foreach (var scopeHandle in reader.GetLocalScopes(methodHandle))
                {
                    try
                    {
                        var scope = reader.GetLocalScope(scopeHandle);
                        if (ilOffset < scope.StartOffset)
                        {
                            // scopes are sorted by StartOffset, hence all scopes that follow can't contain ilOffset
                            reuseSpanEnd = Math.Min(reuseSpanEnd, (uint)scope.StartOffset);
                            break;
                        }

                        if (ilOffset >= scope.EndOffset)
                        {
                            // ilOffset is not in this scope, go to next one
                            reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.EndOffset);
                            continue;
                        }

                        // reuse span is a subspan of the inner-most scope containing the IL offset:
                        reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.StartOffset);
                        reuseSpanEnd   = Math.Min(reuseSpanEnd, (uint)scope.EndOffset);

                        // imports (use the inner-most):
                        innerMostImportScope = scope.ImportScope;

                        // locals (from all contained scopes):
                        foreach (var variableHandle in scope.GetLocalVariables())
                        {
                            var variable = reader.GetLocalVariable(variableHandle);
                            if ((variable.Attributes & LocalVariableAttributes.DebuggerHidden) != 0)
                            {
                                continue;
                            }

                            localVariableNamesBuilder.SetItem(
                                variable.Index,
                                reader.GetString(variable.Name)
                                );

                            var dynamicFlags = ReadDynamicCustomDebugInformation(
                                reader,
                                variableHandle
                                );
                            if (!dynamicFlags.IsDefault)
                            {
                                lazyDynamicLocalsBuilder ??= ImmutableDictionary.CreateBuilder <
                                    int,
                                    ImmutableArray <bool>
                                    >();
                                lazyDynamicLocalsBuilder[variable.Index] = dynamicFlags;
                            }

                            var tupleElementNames = ReadTupleCustomDebugInformation(
                                reader,
                                variableHandle
                                );
                            if (!tupleElementNames.IsDefault)
                            {
                                lazyTupleLocalsBuilder ??= ImmutableDictionary.CreateBuilder <
                                    int,
                                    ImmutableArray <string?>
                                    >();
                                lazyTupleLocalsBuilder[variable.Index] = tupleElementNames;
                            }
                        }

                        // constants (from all contained scopes):
                        foreach (var constantHandle in scope.GetLocalConstants())
                        {
                            var constant = reader.GetLocalConstant(constantHandle);

                            var sigReader = reader.GetBlobReader(constant.Signature);
                            symbolProvider.DecodeLocalConstant(
                                ref sigReader,
                                out var typeSymbol,
                                out var value
                                );

                            var name         = reader.GetString(constant.Name);
                            var dynamicFlags = ReadDynamicCustomDebugInformation(
                                reader,
                                constantHandle
                                );
                            var tupleElementNames = ReadTupleCustomDebugInformation(
                                reader,
                                constantHandle
                                );
                            localConstantsBuilder.Add(
                                symbolProvider.GetLocalConstant(
                                    name,
                                    typeSymbol,
                                    value,
                                    dynamicFlags,
                                    tupleElementNames
                                    )
                                );
                        }
                    }
                    catch (Exception e)
                        when(e is UnsupportedSignatureContent || e is BadImageFormatException)
                        {
                            // ignore scopes with invalid data
                        }
                }
            }
            finally
            {
                localVariableNames = localVariableNamesBuilder.ToImmutableAndFree();
                localConstants     = localConstantsBuilder.ToImmutableAndFree();
                dynamicLocalMap    = lazyDynamicLocalsBuilder?.ToImmutable();
                tupleLocalMap      = lazyTupleLocalsBuilder?.ToImmutable();
                reuseSpan          = new ILSpan(reuseSpanStart, reuseSpanEnd);
            }

            var importGroupsBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance();

            var externAliasesBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance();

            if (!innerMostImportScope.IsNil)
            {
                PopulateImports(
                    reader,
                    innerMostImportScope,
                    symbolProvider,
                    isVisualBasicMethod,
                    importGroupsBuilder,
                    externAliasesBuilder
                    );
            }

            importGroups  = importGroupsBuilder.ToImmutableAndFree();
            externAliases = externAliasesBuilder.ToImmutableAndFree();
        }