public void AddMissingDependency_MissingMemberOfSupportedType_TypeIsNotMarkedMissing()
        {
            var targets = TargetPlatforms(2);
            var type = new MemberInfo
            {
                MemberDocId = "T:Spam.Spam",
                IsSupportedAcrossTargets = true,
                TargetStatus = targets.Select(t => new Version(t.Version.ToString())).ToList()
            };

            var missingMember = MissingMember(type.MemberDocId, "Eggs");
            missingMember.TargetStatus = new List<Version>
            {
                new Version("1.0"),
                null
            };

            var reportingResult = new ReportingResult(targets, new List<MemberInfo>() { type }, Guid.NewGuid().ToString(), AnalyzeRequestFlags.None);
            reportingResult.AddMissingDependency(null, missingMember, "Add more spam.");

            var typeIsMarkedMissing = reportingResult.GetMissingTypes()
                .First(t => string.Equals(t.TypeName, type.MemberDocId, StringComparison.Ordinal))
                .IsMissing;
            Assert.False(typeIsMarkedMissing);
        }
        public IEnumerable<ISourceMappedItem> GetSourceInfo(IEnumerable<string> assemblyPaths, ReportingResult report)
        {
            var items = new List<ISourceMappedItem>();

            _textOutput.WriteLine();
            _textOutput.WriteLine(LocalizedStrings.FindingSourceLineInformationFor);

            foreach (var assembly in assemblyPaths)
            {
                using (var task = _progressReporter.StartTask(string.Format("\t{0}\b\b\b", Path.GetFileName(assembly))))
                {
                    try
                    {
                        var pdbPath = _fileSystem.ChangeFileExtension(assembly, "pdb");

                        if (!_fileSystem.FileExists(pdbPath))
                        {
                            _progressReporter.ReportIssue(string.Format(LocalizedStrings.PdbNotFoundFormat, assembly));
                            task.Abort();
                            continue;
                        }

                        items.AddRange(GetSourceInfo(assembly, pdbPath, report));
                    }
                    catch (PortabilityAnalyzerException)
                    {
                        task.Abort();
                    }
                }
            }

            return items;
        }
        public CciMetadataTraverser(ReportingResult analysis, PdbReader pdbReader)
        {
            _analysis = analysis;
            _pdbReader = pdbReader;

            var missingMembers = from type in analysis.GetMissingTypes()
                                 from member in type.MissingMembers
                                 select member;

            _interestingMethods = missingMembers
                .ToDictionary(m => m.MemberName, m => m);

            _interestingTypes = analysis.GetMissingTypes()
                .Where(type => type.IsMissing)
                .ToDictionary(t => t.DocId, t => t);
        }
        public void AddMissingDependency_MemberOfUnidentifiedType_TypeAddedToMissingTypes()
        {
            var targets = TargetPlatforms(2);
            var typeDocId = "T:Spam.Spam";
            var missingMember = MissingMember(typeDocId, "Eggs");
            missingMember.TargetStatus = new List<Version>
            {
                new Version("1.0"),
                null
            };

            var reportingResult = new ReportingResult(targets, new List<MemberInfo>(), Guid.NewGuid().ToString(), AnalyzeRequestFlags.None);
            reportingResult.AddMissingDependency(null, missingMember, "Add more spam.");

            var typeWasAdded = reportingResult.GetMissingTypes().Any(t => string.Equals(t.DocId, typeDocId, StringComparison.Ordinal));
            Assert.True(typeWasAdded);
        }
        public override IEnumerable<ISourceMappedItem> GetSourceInfo(string assemblyPath, string pdbPath, ReportingResult report)
        {
            using (var host = new HostEnvironment())
            using (var pdbFs = File.OpenRead(pdbPath))
            using (var pdbReader = new PdbReader(pdbFs, host))
            {
                var metadataVisitor = new CciMetadataTraverser(report, pdbReader);
                var traverser = new MetadataTraverser
                {
                    PreorderVisitor = metadataVisitor,
                    TraverseIntoMethodBodies = true
                };

                var cciAssembly = host.LoadAssembly(assemblyPath);
                traverser.Traverse(cciAssembly);

                return metadataVisitor.FoundItems;
            }
        }
 public abstract IEnumerable<ISourceMappedItem> GetSourceInfo(string assemblyPath, string pdbPath, ReportingResult report);
        public ReportingResult ComputeReport(
            IList<FrameworkName> targets,
            string submissionId,
            AnalyzeRequestFlags requestFlags,
            IDictionary<MemberInfo, ICollection<AssemblyInfo>> allDependencies,
            IList<MemberInfo> missingDependencies,
            IDictionary<string, ICollection<string>> unresolvedAssemblies,
            IList<string> unresolvedUserAssemblies,
            IEnumerable<string> assembliesWithErrors)
        {
            var types = allDependencies.Keys.Where(dep => dep.TypeDocId == null);
            ReportingResult result = new ReportingResult(targets, types, submissionId, requestFlags);

            missingDependencies
                .AsParallel()
                .ForAll((Action<MemberInfo>)((item) =>
                {
                    // the calling assemblies are in Finder...
                    if (allDependencies == null)
                    {
                        lock (result)
                        {
                            result.AddMissingDependency(null, item, item.RecommendedChanges);
                        }
                    }
                    else
                    {
                        ICollection<AssemblyInfo> calledIn;
                        if (!allDependencies.TryGetValue(item, out calledIn))
                            return;

                        foreach (var callingAsm in calledIn)
                        {
                            lock (result)
                            {
                                result.AddMissingDependency(callingAsm, item, item.RecommendedChanges);
                            }
                        }
                    }
                }));

            if (assembliesWithErrors != null)
            {
                foreach (var error in assembliesWithErrors)
                {
                    result.AddAssemblyWithError(error);
                }
            }

            foreach (var unresolvedAssembly in unresolvedUserAssemblies)
            {
                result.AddUnresolvedUserAssembly(unresolvedAssembly, unresolvedAssemblies == null ? Enumerable.Empty<string>() : unresolvedAssemblies[unresolvedAssembly]);
            }

            // Compute per assembly report
            if (allDependencies != null)
            {
                var perAssemblyUsage = ComputePerAssemblyUsage(targets, missingDependencies, allDependencies);
                result.SetAssemblyUsageInfo(perAssemblyUsage);

                // Compute the map of assemblyInfo to name
                var assemblyNameMap = ComputeAssemblyNames(perAssemblyUsage);
                result.SetAssemblyNameMap(assemblyNameMap);
            }

            return result;
        }
        public void AddMissingDependency_MemberOfUnidentifiedType_TypeInheritsMemberTargetStatus()
        {
            var targets = TargetPlatforms(2);
            var typeDocId = "T:Spam.Spam";
            var missingMember = MissingMember(typeDocId, "Eggs");
            missingMember.TargetStatus = new List<Version>
            {
                new Version("1.0"),
                null
            };

            var reportingResult = new ReportingResult(targets, new List<MemberInfo>(), Guid.NewGuid().ToString(), AnalyzeRequestFlags.None);
            reportingResult.AddMissingDependency(null, missingMember, "Add more spam.");

            var type = reportingResult.GetMissingTypes()
                .First(t => string.Equals(t.TypeName, typeDocId, StringComparison.Ordinal));

            Assert.True(missingMember.TargetStatus.Count == type.TargetVersionStatus.Count()
                     && missingMember.TargetStatus.All(v => type.TargetVersionStatus.Contains(v)));
        }