Exemple #1
0
 public void Dispose()
 {
     _nodeStack.Dispose();
     _triviaStack.Dispose();
     _tokenStack?.Free();
     _discriminatorStack?.Free();
 }
        private static int IndexOfCorLibrary(ImmutableArray <AssemblyData> assemblies, IReadOnlyDictionary <string, List <ReferencedAssemblyIdentity> > assemblyReferencesBySimpleName, bool supersedeLowerVersions)
        {
            // Figure out COR library for this compilation.
            ArrayBuilder <int> corLibraryCandidates = null;

            for (int i = 1; i < assemblies.Length; i++)
            {
                var assembly = assemblies[i];

                // The logic about deciding what assembly is a candidate for being a Cor library here and in
                // Microsoft.CodeAnalysis.VisualBasic.CommandLineCompiler.ResolveMetadataReferencesFromArguments
                // should be equivalent.

                // Linked references cannot be used as COR library.
                // References containing NoPia local types also cannot be used as COR library.
                if (!assembly.IsLinked &&
                    assembly.AssemblyReferences.Length == 0 &&
                    !assembly.ContainsNoPiaLocalTypes &&
                    (!supersedeLowerVersions || !IsSuperseded(assembly.Identity, assemblyReferencesBySimpleName)))
                {
                    // We have referenced assembly that doesn't have assembly references,
                    // check if it declares baseless System.Object.

                    if (assembly.DeclaresTheObjectClass)
                    {
                        if (corLibraryCandidates == null)
                        {
                            corLibraryCandidates = ArrayBuilder <int> .GetInstance();
                        }

                        // This could be the COR library.
                        corLibraryCandidates.Add(i);
                    }
                }
            }

            // If there is an ambiguous match, pretend there is no COR library.
            // TODO: figure out if we need to be able to resolve this ambiguity.
            if (corLibraryCandidates != null)
            {
                if (corLibraryCandidates.Count == 1)
                {
                    // TODO: need to make sure we error if such assembly declares local type in source.
                    int result = corLibraryCandidates[0];
                    corLibraryCandidates.Free();
                    return(result);
                }
                else
                {
                    // TODO: C# seems to pick the first one (but produces warnings when looking up predefined types).
                    // See PredefinedTypes::Init(ErrorHandling*).
                    corLibraryCandidates.Free();
                }
            }

            // If we have assembly being built and no references,
            // assume the assembly we are building is the COR library.
            if (assemblies.Length == 1 && assemblies[0].AssemblyReferences.Length == 0)
            {
                return(0);
            }

            return(-1);
        }
        /// <summary>
        /// Get the import strings for a given method, following forward pointers as necessary.
        /// </summary>
        /// <returns>
        /// For each namespace enclosing the method, a list of import strings, innermost to outermost.
        /// There should always be at least one entry, for the global namespace.
        /// </returns>
        public static ImmutableArray <ImmutableArray <string> > GetCSharpGroupedImportStrings(this ISymUnmanagedReader reader, int methodToken, int methodVersion, out ImmutableArray <string> externAliasStrings)
        {
            externAliasStrings = default(ImmutableArray <string>);

            ImmutableArray <short> groupSizes = default(ImmutableArray <short>);
            bool seenForward = false;

RETRY:
            byte[] bytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion);
            if (bytes == null)
            {
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            foreach (var record in GetCustomDebugInfoRecords(bytes))
            {
                switch (record.Kind)
                {
                case CustomDebugInfoKind.UsingInfo:
                    if (!groupSizes.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Expected at most one Using record for method {0}", FormatMethodToken(methodToken)));
                    }

                    groupSizes = DecodeUsingRecord(record.Data);
                    break;

                case CustomDebugInfoKind.ForwardInfo:
                    if (!externAliasStrings.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Did not expect both Forward and ForwardToModule records for method {0}", FormatMethodToken(methodToken)));
                    }

                    methodToken = DecodeForwardRecord(record.Data);

                    // Follow at most one forward link (as in FUNCBRECEE::ensureNamespaces).
                    // NOTE: Dev11 may produce chains of forward links (e.g. for System.Collections.Immutable).
                    if (!seenForward)
                    {
                        seenForward = true;
                        goto RETRY;
                    }

                    break;

                case CustomDebugInfoKind.ForwardToModuleInfo:
                    if (!externAliasStrings.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Expected at most one ForwardToModule record for method {0}", FormatMethodToken(methodToken)));
                    }

                    int moduleInfoMethodToken = DecodeForwardToModuleRecord(record.Data);
                    ImmutableArray <string> allModuleInfoImportStrings = reader.GetMethodByVersion(moduleInfoMethodToken, methodVersion).GetImportStrings();
                    ArrayBuilder <string>   externAliasBuilder         = ArrayBuilder <string> .GetInstance();

                    foreach (string importString in allModuleInfoImportStrings)
                    {
                        if (IsCSharpExternAliasInfo(importString))
                        {
                            externAliasBuilder.Add(importString);
                        }
                    }

                    externAliasStrings = externAliasBuilder.ToImmutableAndFree();
                    break;
                }
            }

            if (groupSizes.IsDefault)
            {
                // This can happen in malformed PDBs (e.g. chains of forwards).
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            var method = reader.GetMethodByVersion(methodToken, methodVersion);

            if (method == null)
            {
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            ImmutableArray <string> importStrings = method.GetImportStrings();
            int numImportStrings = importStrings.Length;

            ArrayBuilder <ImmutableArray <string> > resultBuilder = ArrayBuilder <ImmutableArray <string> > .GetInstance(groupSizes.Length);

            ArrayBuilder <string> groupBuilder = ArrayBuilder <string> .GetInstance();

            int pos = 0;

            foreach (short groupSize in groupSizes)
            {
                for (int i = 0; i < groupSize; i++, pos++)
                {
                    if (pos >= numImportStrings)
                    {
                        throw new InvalidOperationException(string.Format("Group size indicates more imports than there are import strings (method {0}).", FormatMethodToken(methodToken)));
                    }

                    string importString = importStrings[pos];
                    if (IsCSharpExternAliasInfo(importString))
                    {
                        throw new InvalidOperationException(string.Format("Encountered extern alias info before all import strings were consumed (method {0}).", FormatMethodToken(methodToken)));
                    }

                    groupBuilder.Add(importString);
                }

                resultBuilder.Add(groupBuilder.ToImmutable());
                groupBuilder.Clear();
            }

            if (externAliasStrings.IsDefault)
            {
                Debug.Assert(groupBuilder.Count == 0);

                // Extern alias detail strings (prefix "Z") are not included in the group counts.
                for (; pos < numImportStrings; pos++)
                {
                    string importString = importStrings[pos];
                    if (!IsCSharpExternAliasInfo(importString))
                    {
                        throw new InvalidOperationException(string.Format("Expected only extern alias info strings after consuming the indicated number of imports (method {0}).", FormatMethodToken(methodToken)));
                    }

                    groupBuilder.Add(importString);
                }

                externAliasStrings = groupBuilder.ToImmutableAndFree();
            }
            else
            {
                groupBuilder.Free();

                if (pos < numImportStrings)
                {
                    throw new InvalidOperationException(string.Format("Group size indicates fewer imports than there are import strings (method {0}).", FormatMethodToken(methodToken)));
                }
            }

            return(resultBuilder.ToImmutableAndFree());
        }
Exemple #4
0
        protected void GetCompilationReferences(
            TCompilation compilation,
            DiagnosticBag diagnostics,
            out ImmutableArray <MetadataReference> references,
            out IDictionary <string, MetadataReference> boundReferenceDirectives,
            out ImmutableArray <Location> referenceDirectiveLocations)
        {
            boundReferenceDirectives = null;

            ArrayBuilder <MetadataReference> referencesBuilder = ArrayBuilder <MetadataReference> .GetInstance();

            ArrayBuilder <Location> referenceDirectiveLocationsBuilder = null;

            try
            {
                foreach (var referenceDirective in compilation.ReferenceDirectives)
                {
                    // we already successfully bound #r with the same value:
                    if (boundReferenceDirectives != null && boundReferenceDirectives.ContainsKey(referenceDirective.File))
                    {
                        continue;
                    }

                    MetadataReference boundReference = ResolveReferenceDirective(referenceDirective.File, referenceDirective.Location, compilation);
                    if (boundReference == null)
                    {
                        diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotFound, referenceDirective.Location, referenceDirective.File));
                        continue;
                    }

                    if (boundReferenceDirectives == null)
                    {
                        boundReferenceDirectives           = new Dictionary <string, MetadataReference>();
                        referenceDirectiveLocationsBuilder = ArrayBuilder <Location> .GetInstance();
                    }

                    referencesBuilder.Add(boundReference);
                    referenceDirectiveLocationsBuilder.Add(referenceDirective.Location);
                    boundReferenceDirectives.Add(referenceDirective.File, boundReference);
                }

                // Workaround for bug #531342: include facades if we reference a Portable Library:
                referencesBuilder.AddRange(ResolveFacadeReferences(compilation));

                // add external reference at the end, so that they are processed first:
                referencesBuilder.AddRange(compilation.ExternalReferences);

                if (boundReferenceDirectives == null)
                {
                    // no directive references resolved successfully:
                    boundReferenceDirectives = SpecializedCollections.EmptyDictionary <string, MetadataReference>();
                }

                references = referencesBuilder.ToImmutable();
                referenceDirectiveLocations = referenceDirectiveLocationsBuilder == null ? ImmutableArray <Location> .Empty : referenceDirectiveLocationsBuilder.ToImmutableAndFree();
            }
            finally
            {
                // Put this in a finally because we have tests that (intentionally) cause ResolveReferenceDirective to throw and
                // we don't want to clutter the test output with leak reports.
                referencesBuilder.Free();
            }
        }
 internal void Free() => _sourcesAdded.Free();
        protected void GetCompilationReferences(
            TCompilation compilation,
            DiagnosticBag diagnostics,
            out ImmutableArray <MetadataReference> references,
            out IDictionary <ValueTuple <string, string>, MetadataReference> boundReferenceDirectives,
            out ImmutableArray <Location> referenceDirectiveLocations)
        {
            boundReferenceDirectives = null;

            ArrayBuilder <MetadataReference> referencesBuilder = ArrayBuilder <MetadataReference> .GetInstance();

            ArrayBuilder <Location> referenceDirectiveLocationsBuilder = null;

            try
            {
                foreach (var referenceDirective in compilation.ReferenceDirectives)
                {
                    if (compilation.Options.MetadataReferenceResolver == null)
                    {
                        diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataReferencesNotSupported, referenceDirective.Location));
                        break;
                    }

                    // we already successfully bound #r with the same value:
                    if (boundReferenceDirectives != null && boundReferenceDirectives.ContainsKey(ValueTuple.Create(referenceDirective.Location.SourceTree.FilePath, referenceDirective.File)))
                    {
                        continue;
                    }

                    MetadataReference boundReference = ResolveReferenceDirective(referenceDirective.File, referenceDirective.Location, compilation);
                    if (boundReference == null)
                    {
                        diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotFound, referenceDirective.Location, referenceDirective.File));
                        continue;
                    }

                    if (boundReferenceDirectives == null)
                    {
                        boundReferenceDirectives           = new Dictionary <ValueTuple <string, string>, MetadataReference>();
                        referenceDirectiveLocationsBuilder = ArrayBuilder <Location> .GetInstance();
                    }

                    referencesBuilder.Add(boundReference);
                    referenceDirectiveLocationsBuilder.Add(referenceDirective.Location);
                    boundReferenceDirectives.Add(ValueTuple.Create(referenceDirective.Location.SourceTree.FilePath, referenceDirective.File), boundReference);
                }

                // add external reference at the end, so that they are processed first:
                referencesBuilder.AddRange(compilation.ExternalReferences);

                // Add all explicit references of the previous script compilation.
                var previousScriptCompilation = compilation.ScriptCompilationInfo?.PreviousScriptCompilation;
                if (previousScriptCompilation != null)
                {
                    referencesBuilder.AddRange(previousScriptCompilation.GetBoundReferenceManager().ExplicitReferences);
                }

                if (boundReferenceDirectives == null)
                {
                    // no directive references resolved successfully:
                    boundReferenceDirectives = SpecializedCollections.EmptyDictionary <ValueTuple <string, string>, MetadataReference>();
                }

                references = referencesBuilder.ToImmutable();
                referenceDirectiveLocations = referenceDirectiveLocationsBuilder?.ToImmutableAndFree() ?? ImmutableArray <Location> .Empty;
            }
            finally
            {
                // Put this in a finally because we have tests that (intentionally) cause ResolveReferenceDirective to throw and
                // we don't want to clutter the test output with leak reports.
                referencesBuilder.Free();
            }
        }
Exemple #7
0
        private AssemblyMetadata CreateAssemblyMetadata(ShadowCopy manifestModuleCopy)
        {
            // We don't need to use the global metadata cache here since the shadow copy
            // won't change and is private to us - only users of the same shadow copy provider see it.

            ArrayBuilder <ModuleMetadata> moduleBuilder = null;

            bool           fault          = true;
            ModuleMetadata manifestModule = null;

            try
            {
                manifestModule = CreateModuleMetadata(manifestModuleCopy);

                string originalDirectory = null, shadowCopyDirectory = null;
                foreach (string moduleName in manifestModule.GetModuleNames())
                {
                    if (moduleBuilder == null)
                    {
                        moduleBuilder = ArrayBuilder <ModuleMetadata> .GetInstance();

                        moduleBuilder.Add(manifestModule);
                        originalDirectory   = Path.GetDirectoryName(manifestModuleCopy.OriginalPath);
                        shadowCopyDirectory = Path.GetDirectoryName(manifestModuleCopy.FullPath);
                    }

                    string originalPath   = Path.Combine(originalDirectory, moduleName);
                    string shadowCopyPath = Path.Combine(shadowCopyDirectory, moduleName);

                    var moduleCopy = CopyFile(originalPath, shadowCopyPath);
                    moduleBuilder.Add(CreateModuleMetadata(moduleCopy));
                }

                var modules = (moduleBuilder != null) ? moduleBuilder.ToImmutable() : ImmutableArray.Create(manifestModule);

                fault = false;
                return(new AssemblyMetadata(modules));
            }
            finally
            {
                if (fault)
                {
                    if (manifestModule != null)
                    {
                        manifestModule.Dispose();
                    }

                    if (moduleBuilder != null)
                    {
                        for (int i = 1; i < moduleBuilder.Count; i++)
                        {
                            moduleBuilder[i].Dispose();
                        }
                    }
                }

                if (moduleBuilder != null)
                {
                    moduleBuilder.Free();
                }
            }
        }