private void AddLibraryProperties(Library library, PackageSpec packageSpec, NuGetFramework targetFramework)
        {
            var projectStyle = packageSpec.RestoreMetadata?.ProjectStyle ?? ProjectStyle.Unknown;

            library[KnownLibraryProperties.PackageSpec]  = packageSpec;
            library[KnownLibraryProperties.ProjectStyle] = projectStyle;

            if (packageSpec.RestoreMetadata?.Files != null)
            {
                // Record all files that would be in a nupkg
                library[KnownLibraryProperties.ProjectRestoreMetadataFiles]
                    = packageSpec.RestoreMetadata.Files.ToList();
            }

            // Avoid adding these properties for class libraries
            // and other projects which are not fully able to
            // participate in restore.
            if (packageSpec.RestoreMetadata == null ||
                (projectStyle != ProjectStyle.Unknown &&
                 projectStyle != ProjectStyle.PackagesConfig))
            {
                var frameworks = new List <NuGetFramework>(
                    packageSpec.TargetFrameworks.Select(fw => fw.FrameworkName)
                    .Where(fw => !fw.IsUnsupported));

                // Record all frameworks in the project
                library[KnownLibraryProperties.ProjectFrameworks] = frameworks;

                var targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework);

                // FrameworkReducer.GetNearest does not consider ATF since it is used for more than just compat
                if (targetFrameworkInfo.FrameworkName == null && targetFramework is AssetTargetFallbackFramework atfFramework)
                {
                    targetFrameworkInfo = packageSpec.GetTargetFramework(atfFramework.AsFallbackFramework());
                }

                if (targetFrameworkInfo.FrameworkName == null && targetFramework is DualCompatibilityFramework mcfFramework)
                {
                    targetFrameworkInfo = packageSpec.GetTargetFramework(mcfFramework.AsFallbackFramework());
                }

                library[KnownLibraryProperties.TargetFrameworkInformation] = targetFrameworkInfo;

                // Add framework assemblies
                var frameworkAssemblies = targetFrameworkInfo.Dependencies
                                          .Where(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference)
                                          .Select(d => d.Name)
                                          .Distinct(StringComparer.OrdinalIgnoreCase)
                                          .ToList();

                library[KnownLibraryProperties.FrameworkAssemblies] = frameworkAssemblies;

                // Add framework references
                library[KnownLibraryProperties.FrameworkReferences] = targetFrameworkInfo.FrameworkReferences;
            }
        }
        internal List <LibraryDependency> GetSpecDependencies(
            PackageSpec packageSpec,
            NuGetFramework targetFramework)
        {
            var dependencies = new List <LibraryDependency>();

            if (packageSpec != null)
            {
                // Add dependencies section
                dependencies.AddRange(packageSpec.Dependencies);

                // Add framework specific dependencies
                var targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework);

                if (!_useLegacyAssetTargetFallbackBehavior)
                {
                    if (targetFrameworkInfo.FrameworkName == null && targetFramework is AssetTargetFallbackFramework atfFramework)
                    {
                        targetFrameworkInfo = packageSpec.GetTargetFramework(atfFramework.AsFallbackFramework());
                    }
                }

                dependencies.AddRange(targetFrameworkInfo.Dependencies);

                if (packageSpec.RestoreMetadata?.CentralPackageVersionsEnabled == true &&
                    packageSpec.RestoreMetadata?.CentralPackageTransitivePinningEnabled == true)
                {
                    var dependencyNamesSet = new HashSet <string>(targetFrameworkInfo.Dependencies.Select(d => d.Name), StringComparer.OrdinalIgnoreCase);
                    dependencies.AddRange(targetFrameworkInfo.CentralPackageVersions
                                          .Where(item => !dependencyNamesSet.Contains(item.Key))
                                          .Select(item => new LibraryDependency()
                    {
                        LibraryRange            = new LibraryRange(item.Value.Name, item.Value.VersionRange, LibraryDependencyTarget.Package),
                        VersionCentrallyManaged = true,
                        ReferenceType           = LibraryDependencyReferenceType.None,
                    }));
                }

                // Remove all framework assemblies
                dependencies.RemoveAll(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference);

                for (var i = 0; i < dependencies.Count; i++)
                {
                    // Clone the library dependency so we can safely modify it. The instance cloned here is from the
                    // original package spec, which should not be modified.
                    dependencies[i] = dependencies[i].Clone();
                    // Remove "project" from the allowed types for this dependency
                    // This will require that projects referenced by an msbuild project
                    // must be external projects.
                    dependencies[i].LibraryRange.TypeConstraint &= ~LibraryDependencyTarget.Project;
                }
            }

            return(dependencies);
        }
        private static List <LibraryDependency> GetSpecDependencies(
            PackageSpec packageSpec,
            NuGetFramework targetFramework)
        {
            var dependencies = new List <LibraryDependency>();

            if (packageSpec != null)
            {
                // Add dependencies section
                dependencies.AddRange(packageSpec.Dependencies);

                // Add framework specific dependencies
                var targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework);
                dependencies.AddRange(targetFrameworkInfo.Dependencies);

                // Remove all framework assemblies
                dependencies.RemoveAll(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference);

                for (var i = 0; i < dependencies.Count; i++)
                {
                    // Clone the library dependency so we can safely modify it. The instance cloned here is from the
                    // original package spec, which should not be modified.
                    dependencies[i] = dependencies[i].Clone();

                    // Remove "project" from the allowed types for this dependency
                    // This will require that projects referenced by an msbuild project
                    // must be external projects.
                    dependencies[i].LibraryRange.TypeConstraint &= ~LibraryDependencyTarget.Project;
                }
            }

            return(dependencies);
        }
        private static void AddLibraryProperties(Library library, PackageSpec packageSpec, NuGetFramework targetFramework, string msbuildPath)
        {
            var projectStyle = packageSpec.RestoreMetadata?.ProjectStyle ?? ProjectStyle.Unknown;

            library[KnownLibraryProperties.PackageSpec]  = packageSpec;
            library[KnownLibraryProperties.ProjectStyle] = projectStyle;

            if (packageSpec.RestoreMetadata?.Files != null)
            {
                // Record all files that would be in a nupkg
                library[KnownLibraryProperties.ProjectRestoreMetadataFiles]
                    = packageSpec.RestoreMetadata.Files.ToList();
            }

            // Avoid adding these properties for class libraries
            // and other projects which are not fully able to
            // participate in restore.
            if (packageSpec.RestoreMetadata == null ||
                (projectStyle != ProjectStyle.Unknown &&
                 projectStyle != ProjectStyle.PackagesConfig))
            {
                var frameworks = new List <NuGetFramework>(
                    packageSpec.TargetFrameworks.Select(fw => fw.FrameworkName)
                    .Where(fw => !fw.IsUnsupported));

                // Record all frameworks in the project
                library[KnownLibraryProperties.ProjectFrameworks] = frameworks;

                var targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework);
                library[KnownLibraryProperties.TargetFrameworkInformation] = targetFrameworkInfo;

                // Add framework references
                var frameworkReferences = targetFrameworkInfo.Dependencies
                                          .Where(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference)
                                          .Select(d => d.Name)
                                          .Distinct(StringComparer.OrdinalIgnoreCase)
                                          .ToList();

                library[KnownLibraryProperties.FrameworkAssemblies] = frameworkReferences;
            }
        }
        public Library GetLibrary(LibraryRange libraryRange, NuGetFramework targetFramework, string rootPath)
        {
            Library library = null;
            var     name    = libraryRange.Name;

            ExternalProjectReference externalReference = null;
            PackageSpec packageSpec            = null;
            bool        resolvedUsingDirectory = false;

            // Check the external references first
            if (_externalProjectsByName.TryGetValue(name, out externalReference))
            {
                packageSpec = externalReference.PackageSpec;
            }
            else if (libraryRange.TypeConstraintAllows(LibraryDependencyTarget.Project))
            {
                // Find the package spec resolver for this root path.
                var specResolver = GetPackageSpecResolver(rootPath);

                // Allow directory look ups unless this constrained to external
                resolvedUsingDirectory = specResolver.TryResolvePackageSpec(name, out packageSpec);
            }

            if (externalReference == null && packageSpec == null)
            {
                // unable to find any projects
                return(null);
            }

            // create a dictionary of dependencies to make sure that no duplicates exist
            var dependencies = new List <LibraryDependency>();
            TargetFrameworkInformation targetFrameworkInfo = null;

            if (packageSpec != null)
            {
                // Add dependencies section
                dependencies.AddRange(packageSpec.Dependencies);

                // Add framework specific dependencies
                targetFrameworkInfo = packageSpec.GetTargetFramework(targetFramework);
                dependencies.AddRange(targetFrameworkInfo.Dependencies);

                // Remove all framework assemblies
                dependencies.RemoveAll(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference);

                // Disallow projects (resolved by directory) for non-xproj msbuild projects.
                // If there is no msbuild path then resolving by directory is allowed.
                // CSProj does not allow directory to directory look up.
                if (XProjUtility.IsMSBuildBasedProject(externalReference?.MSBuildProjectPath))
                {
                    foreach (var dependency in dependencies)
                    {
                        // Remove "project" from the allowed types for this dependency
                        // This will require that projects referenced by an msbuild project
                        // must be external projects.
                        dependency.LibraryRange.TypeConstraint &= ~LibraryDependencyTarget.Project;
                    }
                }
            }

            if (externalReference != null)
            {
                var childReferences     = GetChildReferences(externalReference);
                var childReferenceNames = childReferences.Select(reference => reference.ProjectName).ToList();

                // External references are created without pivoting on the TxM. Here we need to account for this
                // and filter out references except the nearest TxM.
                var filteredExternalDependencies = new HashSet <string>(
                    childReferenceNames,
                    StringComparer.OrdinalIgnoreCase);

                // Non-Xproj projects may only have one TxM, all external references should be
                // included if this is an msbuild based project.
                if (packageSpec != null &&
                    !XProjUtility.IsMSBuildBasedProject(externalReference.MSBuildProjectPath))
                {
                    // Create an exclude list of all references from the non-selected TxM
                    // Start with all framework specific references
                    var allFrameworkDependencies = GetProjectNames(
                        packageSpec.TargetFrameworks.SelectMany(info => info.Dependencies));

                    var excludedDependencies = new HashSet <string>(
                        allFrameworkDependencies,
                        StringComparer.OrdinalIgnoreCase);

                    // Then clear out excluded dependencies that are found in the good dependency list
                    foreach (var dependency in GetProjectNames(dependencies))
                    {
                        excludedDependencies.Remove(dependency);
                    }

                    // Remove excluded dependencies from the external list
                    foreach (var excluded in excludedDependencies)
                    {
                        filteredExternalDependencies.Remove(excluded);
                    }
                }

                // Set all dependencies from project.json to external if an external match was passed in
                // This is viral and keeps p2ps from looking into directories when we are going down
                // a path already resolved by msbuild.
                foreach (var dependency in dependencies.Where(d => IsProject(d) &&
                                                              filteredExternalDependencies.Contains(d.Name)))
                {
                    dependency.LibraryRange.TypeConstraint = LibraryDependencyTarget.ExternalProject;
                }

                // Add dependencies passed in externally
                // These are usually msbuild references which have less metadata, they have
                // the lowest priority.
                // Note: Only add in dependencies that are in the filtered list to avoid getting the wrong TxM
                dependencies.AddRange(childReferences
                                      .Where(reference => filteredExternalDependencies.Contains(reference.ProjectName))
                                      .Select(reference => new LibraryDependency
                {
                    LibraryRange = new LibraryRange
                    {
                        Name           = reference.ProjectName,
                        VersionRange   = VersionRange.Parse("1.0.0"),
                        TypeConstraint = LibraryDependencyTarget.ExternalProject
                    }
                }));
            }

            // Remove duplicate dependencies. A reference can exist both in csproj and project.json
            // dependencies is already ordered by importance here
            var uniqueDependencies = new List <LibraryDependency>(dependencies.Count);
            var projectNames       = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var project in dependencies)
            {
                if (projectNames.Add(project.Name))
                {
                    uniqueDependencies.Add(project);
                }
            }

            library = new Library
            {
                LibraryRange = libraryRange,
                Identity     = new LibraryIdentity
                {
                    Name    = externalReference?.ProjectName ?? packageSpec.Name,
                    Version = packageSpec?.Version ?? NuGetVersion.Parse("1.0.0"),
                    Type    = LibraryType.Project,
                },
                Path         = packageSpec?.FilePath,
                Dependencies = uniqueDependencies,
                Resolved     = true
            };

            if (packageSpec != null)
            {
                library[KnownLibraryProperties.PackageSpec] = packageSpec;
            }

            string msbuildPath = null;

            if (externalReference == null)
            {
                // Build the path to the .xproj file
                // If it exists add it to the library properties for the lock file
                var projectDir = Path.GetDirectoryName(packageSpec.FilePath);
                var xprojPath  = Path.Combine(projectDir, packageSpec.Name + ".xproj");

                if (File.Exists(xprojPath))
                {
                    msbuildPath = xprojPath;
                }
            }
            else
            {
                msbuildPath = externalReference.MSBuildProjectPath;
            }

            if (msbuildPath != null)
            {
                library[KnownLibraryProperties.MSBuildProjectPath] = msbuildPath;
            }

            if (packageSpec != null)
            {
                // Record all frameworks in the project
                library[KnownLibraryProperties.ProjectFrameworks] = new List <NuGetFramework>(
                    packageSpec.TargetFrameworks.Select(fw => fw.FrameworkName));
            }

            if (targetFrameworkInfo != null)
            {
                library[KnownLibraryProperties.TargetFrameworkInformation] = targetFrameworkInfo;

                // Add framework references
                var frameworkReferences = targetFrameworkInfo.Dependencies
                                          .Where(d => d.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference)
                                          .Select(d => d.Name)
                                          .Distinct(StringComparer.OrdinalIgnoreCase)
                                          .ToList();

                library[KnownLibraryProperties.FrameworkAssemblies] = frameworkReferences;

                // Add a compile asset for msbuild to xproj projects
                if (targetFrameworkInfo.FrameworkName != null &&
                    msbuildPath?.EndsWith(".xproj", StringComparison.OrdinalIgnoreCase) == true)
                {
                    var tfmFolder = targetFrameworkInfo.FrameworkName.GetShortFolderName();

                    // Projects under solution folders will have names such as src\\MyProject
                    // For the purpose of finding the output assembly just take the last part of the name
                    var projectName = packageSpec.Name.Split(
                        new char[] { '/', '\\' },
                        StringSplitOptions.RemoveEmptyEntries)
                                      .Last();

                    // Currently the assembly name cannot be changed for xproj, we can construct the path to where
                    // the output should be.
                    var asset = $"{tfmFolder}/{projectName}.dll";
                    library[KnownLibraryProperties.CompileAsset] = asset;
                    library[KnownLibraryProperties.RuntimeAsset] = asset;
                }
            }

            return(library);
        }