Example #1
0
        private bool TryCreateQualifier(NugetAnalyzedPackage analyzedPackage, out IStatement statement)
        {
            List <PathAtom> compatibleTfms = new List <PathAtom>();

            if (analyzedPackage.IsNetStandardPackageOnly)
            {
                compatibleTfms.AddRange(m_nugetFrameworkMonikers.NetStandardToFullFrameworkCompatibility);
            }

            FindAllCompatibleFrameworkMonikers(analyzedPackage,
                                               (List <PathAtom> monikers) => compatibleTfms.AddRange(monikers),
                                               m_nugetFrameworkMonikers.FullFrameworkVersionHistory,
                                               m_nugetFrameworkMonikers.NetCoreVersionHistory);

            if (compatibleTfms.Count > 0)
            {
                // { targetFramework: 'tf1' | 'tf2' | ... }
                var qualifierType = UnionType(
                    (propertyName: "targetFramework", literalTypes: compatibleTfms.Select(m => m.ToString(m_pathTable.StringTable))),
                    (propertyName: "targetRuntime", literalTypes: m_nugetFrameworkMonikers.SupportedTargetRuntimes)
                    );
                statement = Qualifier(qualifierType);
                return(true);
            }

            statement = null;
            return(false);
        }
        internal static void FindAllCompatibleFrameworkMonikers(NugetAnalyzedPackage analyzedPackage, Action <List <PathAtom> > callback, params List <PathAtom>[] tfmHistory)
        {
            if (analyzedPackage.TargetFrameworks.Count > 0)
            {
                foreach (var versionHistory in tfmHistory)
                {
                    var indices = analyzedPackage.TargetFrameworks
                                  .Select(moniker => versionHistory.IndexOf(moniker))
                                  .Where(idx => idx != -1)
                                  .OrderBy(x => x).ToList();

                    if (indices.IsNullOrEmpty())
                    {
                        continue;
                    }

                    for (int i = 0; i < indices.Count(); i++)
                    {
                        int start = indices[i];
                        int count = (i + 1) > indices.Count() - 1 ? versionHistory.Count() - start : (indices[i + 1] - indices[i]);

                        callback(versionHistory.GetRange(start, count));
                    }
                }
            }
            else
            {
                callback(default(List <PathAtom>));
            }
        }
Example #3
0
        /// <summary>
        /// Constructs a new NugetAnalyzed Package.
        /// </summary>
        /// <remarks>
        /// In case of failure it will log a detailed message and return null.
        /// </remarks>
        public static NugetAnalyzedPackage TryAnalyzeNugetPackage(
            FrontEndContext context,
            NugetFrameworkMonikers nugetFrameworkMonikers,
            XDocument nuSpec,
            PackageOnDisk packageOnDisk,
            Dictionary <string, INugetPackage> packagesOnConfig,
            bool doNotEnforceDependencyVersions)
        {
            Contract.Requires(context != null);
            Contract.Requires(nuSpec != null);
            Contract.Requires(packageOnDisk != null);
            Contract.Requires(packageOnDisk.NuSpecFile.IsValid);

            var analyzedPackage = new NugetAnalyzedPackage(context, nugetFrameworkMonikers, nuSpec, packageOnDisk,
                                                           packagesOnConfig, doNotEnforceDependencyVersions);

            if (!analyzedPackage.TryParseDependenciesFromNuSpec())
            {
                return(null);
            }

            analyzedPackage.ParseManagedSemantics();
            analyzedPackage.UpdateForMissingQualifierConversionFunction();

            return(analyzedPackage);
        }
Example #4
0
        /// <summary>
        /// Performs a depth first search with cycle detection. All descendants of analyzedPackage are pushed into result after it.
        /// </summary>
        /// <returns>
        /// Whether there is a cycle that involves analyzedPackage
        /// </returns>
        private static bool TryVisit(
            IDictionary <string, NugetAnalyzedPackage> allAnalyzedPackages,
            HashSet <NugetAnalyzedPackage> unmarkedPackages,
            HashSet <NugetAnalyzedPackage> temporaryMarkedPackages,
            NugetAnalyzedPackage analyzedPackage,
            IList <NugetAnalyzedPackage> result)
        {
            if (temporaryMarkedPackages.Contains(analyzedPackage))
            {
                // This is a cycle!
                return(false);
            }

            if (unmarkedPackages.Contains(analyzedPackage))
            {
                var isRemoved = unmarkedPackages.Remove(analyzedPackage);
                Contract.Assert(isRemoved);

                temporaryMarkedPackages.Add(analyzedPackage);
                foreach (var dependency in analyzedPackage.Dependencies)
                {
                    Contract.Assert(allAnalyzedPackages.ContainsKey(dependency.GetPackageIdentity()));
                    var analyzedDependency = allAnalyzedPackages[dependency.GetPackageIdentity()];
                    TryVisit(allAnalyzedPackages, unmarkedPackages, temporaryMarkedPackages, analyzedDependency, result);
                }

                isRemoved = temporaryMarkedPackages.Remove(analyzedPackage);
                Contract.Assert(isRemoved);
                result.Add(analyzedPackage);
            }

            return(true);
        }
Example #5
0
        /// <nodoc />
        public NugetSpecGenerator(PathTable pathTable, NugetAnalyzedPackage analyzedPackage)
        {
            m_pathTable       = pathTable;
            m_analyzedPackage = analyzedPackage;
            m_packageOnDisk   = analyzedPackage.PackageOnDisk;

            m_xmlExtension = PathAtom.Create(pathTable.StringTable, ".xml");
            m_pdbExtension = PathAtom.Create(pathTable.StringTable, ".pdb");
        }
Example #6
0
        private bool TryCreateQualifier(NugetAnalyzedPackage analyzedPackage, out IStatement statement)
        {
            if (analyzedPackage.HasTargetFrameworks())
            {
                var targetFrameworks = analyzedPackage.GetTargetFrameworksInStableOrder(m_pathTable);
                // { targetFramework: 'tf1' | 'tf2' }
                var qualifierType = UnionType(propertyName: "targetFramework", literalTypes: targetFrameworks);
                statement = Qualifier(qualifierType);
                return(true);
            }

            statement = null;
            return(false);
        }
Example #7
0
        /// <summary>
        /// Returns a list of target frameworks of a <paramref name="analyzedPackage"/> in sorted order.
        /// </summary>
        public static string[] GetTargetFrameworksInStableOrder(this NugetAnalyzedPackage analyzedPackage, PathTable pathTable)
        {
            Contract.Requires(HasTargetFrameworks(analyzedPackage));

            var targetFrameworks = new HashSet <string>();

            foreach (var kv in analyzedPackage.TargetFrameworkWithFallbacks)
            {
                targetFrameworks.Add(kv.Key.ToString(pathTable.StringTable));
                foreach (var fallback in kv.Value)
                {
                    targetFrameworks.Add(fallback.ToString(pathTable.StringTable));
                }
            }

            return(targetFrameworks.OrderByDescending(f => f).ToArray());
        }
Example #8
0
        private IStatement CreatePackageVariableDeclaration(NugetAnalyzedPackage package)
        {
            IExpression       pkgExpression;
            TypeReferenceNode pkgType;

            if (package.IsManagedPackage)
            {
                // If the package is managed, it is a 'ManagedNugetPackage' and we create a switch based on the current qualifie
                // that defines contents, compile, runtime and dependency items
                pkgType = new TypeReferenceNode("Managed", "ManagedNugetPackage");

                // Computes the switch cases, based on the target framework
                List <ICaseClause> cases = CreateSwitchCasesForTargetFrameworks(package, pkgType);

                pkgExpression = new CallExpression(
                    new ParenthesizedExpression(
                        new ArrowFunction(
                            CollectionUtilities.EmptyArray <IParameterDeclaration>(),
                            new SwitchStatement(
                                PropertyAccess("qualifier", "targetFramework"),
                                new DefaultClause(
                                    new ExpressionStatement(
                                        new CallExpression(
                                            PropertyAccess("Contract", "fail"),
                                            new LiteralExpression("Unsupported target framework")))),
                                cases))));
            }
            else
            {
                // If the package is not managed, it is a 'NugetPackage' with just contents and dependencies
                pkgType       = new TypeReferenceNode("NugetPackage");
                pkgExpression = ObjectLiteral(
                    (name: "contents", PropertyAccess("Contents", "all")),
                    (name: "dependencies", Array(package.Dependencies.Select(CreateImportFromForDependency).ToArray())),
                    (name: "version", new LiteralExpression(package.Version)));
            }

            return
                (new VariableDeclarationBuilder()
                 .Name("pkg")
                 .Visibility(Visibility.Public)
                 .Initializer(pkgExpression)
                 .Type(pkgType)
                 .Build());
        }
        public ISourceFile CreateScriptSourceFile(NugetAnalyzedPackage analyzedPackage)
        {
            var sourceFileBuilder = new SourceFileBuilder();

            // 0. Import {Transformer} from "Sdk.Transformers" to be able to seal directories
            sourceFileBuilder.Statement(ImportDeclaration(new [] { "Transformer" }, "Sdk.Transformers"));

            // 1. Optional import of managed sdk.
            if (analyzedPackage.IsManagedPackage)
            {
                // import * as Managed from 'Sdk.Managed';
                sourceFileBuilder
                .Statement(ImportDeclaration(alias: "Managed", moduleName: "Sdk.Managed"))
                .SemicolonAndBlankLine();
            }

            // 2. Optional qualifier
            if (TryCreateQualifier(analyzedPackage, out var qualifierStatement))
            {
                sourceFileBuilder
                .Statement(qualifierStatement)
                .SemicolonAndBlankLine();
            }

            // 3. Declare a public directory that points to the package root, for convenience reasons
            sourceFileBuilder
            .Statement(new VariableDeclarationBuilder().Name("packageRoot").Initializer(PropertyAccess("Contents", "packageRoot")).Build())
            .SemicolonAndBlankLine();

            // Create a sealed directory declaration with all the package content
            sourceFileBuilder
            .Statement(CreatePackageContents())
            .SemicolonAndBlankLine();

            // @@public export const pkg = ...
            sourceFileBuilder.Statement(CreatePackageVariableDeclaration(analyzedPackage));

            return(sourceFileBuilder.Build());
        }
        /// <summary>
        /// Constructs a new NugetAnalyzed Package.
        /// </summary>
        /// <remarks>
        /// In case of failure it will log a detailed message and return null.
        /// </remarks>
        public static NugetAnalyzedPackage TryAnalyzeNugetPackage(
            FrontEndContext context,
            NugetFrameworkMonikers nugetFrameworkMonikers,
            [CanBeNull] XDocument nuSpec,
            PackageOnDisk packageOnDisk,
            Dictionary <string, INugetPackage> packagesOnConfig,
            bool doNotEnforceDependencyVersions)
        {
            Contract.Requires(context != null);
            Contract.Requires(packageOnDisk != null);

            var analyzedPackage = new NugetAnalyzedPackage(context, nugetFrameworkMonikers, packageOnDisk,
                                                           packagesOnConfig, doNotEnforceDependencyVersions);

            analyzedPackage.ParseManagedSemantics();
            if (nuSpec != null && !analyzedPackage.TryParseDependenciesFromNuSpec(nuSpec))
            {
                return(null);
            }

            return(analyzedPackage);
        }
        private List <ICaseClause> CreateSwitchCasesForTargetFrameworks(NugetAnalyzedPackage analyzedPackage, ITypeNode pkgType)
        {
            var cases = new List <ICaseClause>();

            Contract.Assert(analyzedPackage.TargetFrameworks.Count != 0, "Managed package must have at least one target framework.");

            var valid = analyzedPackage.TargetFrameworks.Exists(moniker => m_nugetFrameworkMonikers.FullFrameworkVersionHistory.Contains(moniker) || m_nugetFrameworkMonikers.NetCoreVersionHistory.Contains(moniker));

            Contract.Assert(valid, "Target framework monikers must exsist and be registered with internal target framework version helpers.");

            foreach (var versionHistory in new List <PathAtom>[] { m_nugetFrameworkMonikers.FullFrameworkVersionHistory, m_nugetFrameworkMonikers.NetCoreVersionHistory })
            {
                FindAllCompatibleFrameworkMonikers(analyzedPackage, (List <PathAtom> monikers) =>
                {
                    if (monikers.Count == 0)
                    {
                        return;
                    }

                    cases.AddRange(monikers.Take(monikers.Count - 1).Select(m => new CaseClause(new LiteralExpression(m.ToString(m_pathTable.StringTable)))));

                    var compile      = new List <IExpression>();
                    var runtime      = new List <IExpression>();
                    var dependencies = new List <IExpression>();

                    // Compile items
                    if (TryGetValueForFrameworkAndFallbacks(analyzedPackage.References, new NugetTargetFramework(monikers.First()), out IReadOnlyList <RelativePath> refAssemblies))
                    {
                        foreach (var assembly in refAssemblies)
                        {
                            compile.Add(CreateSimpleBinary(assembly));
                        }
                    }

                    // Runtime items
                    if (TryGetValueForFrameworkAndFallbacks(analyzedPackage.Libraries, new NugetTargetFramework(monikers.First()), out IReadOnlyList <RelativePath> libAssemblies))
                    {
                        foreach (var assembly in libAssemblies)
                        {
                            runtime.Add(CreateSimpleBinary(assembly));
                        }
                    }

                    // Dependency items
                    if (analyzedPackage.DependenciesPerFramework.TryGetValue(monikers.First(), out IReadOnlyList <INugetPackage> dependencySpecificFrameworks))
                    {
                        foreach (var dependencySpecificFramework in dependencySpecificFrameworks)
                        {
                            dependencies.Add(CreateImportFromForDependency(dependencySpecificFramework));
                        }
                    }

                    cases.Add(
                        new CaseClause(
                            new LiteralExpression(monikers.Last().ToString(m_pathTable.StringTable)),
                            new ReturnStatement(
                                new CallExpression(
                                    PropertyAccess("Managed", "Factory", "createNugetPackage"),
                                    new LiteralExpression(analyzedPackage.Id),
                                    new LiteralExpression(analyzedPackage.Version),
                                    PropertyAccess("Contents", "all"),
                                    Array(compile),
                                    Array(runtime),
                                    Array(new CallExpression(new Identifier("...addIfLazy"),
                                                             new BinaryExpression(
                                                                 new PropertyAccessExpression("qualifier", "targetFramework"),
                                                                 SyntaxKind.EqualsEqualsEqualsToken,
                                                                 new LiteralExpression(monikers.First().ToString(m_pathTable.StringTable))
                                                                 ),
                                                             new ArrowFunction(
                                                                 CollectionUtilities.EmptyArray <IParameterDeclaration>(),
                                                                 Array(dependencies)
                                                                 )
                                                             ))
                                    )
                                )
                            )
                        );
                }, versionHistory);
            }

            return(cases);
        }
Example #12
0
        private List <ICaseClause> CreateSwitchCasesForTargetFrameworks(NugetAnalyzedPackage analyzedPackage, ITypeNode pkgType)
        {
            var cases = new List <ICaseClause>();

            Contract.Assert(analyzedPackage.TargetFrameworks.Count != 0, "Managed package must have at least one target framework.");

            var valid = analyzedPackage.TargetFrameworks.Exists(moniker => m_nugetFrameworkMonikers.FullFrameworkVersionHistory.Contains(moniker) || m_nugetFrameworkMonikers.NetCoreVersionHistory.Contains(moniker));

            Contract.Assert(valid, "Target framework monikers must exsist and be registered with internal target framework version helpers.");

            var allFullFrameworkDeps = m_nugetFrameworkMonikers.FullFrameworkVersionHistory
                                       .SelectMany(m =>
                                                   analyzedPackage.DependenciesPerFramework.TryGetValue(m, out IReadOnlyList <INugetPackage> dependencySpecificFrameworks)
                        ? dependencySpecificFrameworks
                        : new List <INugetPackage>())
                                       .GroupBy(pkg => pkg.Id)
                                       .Select(grp => grp.OrderBy(pkg => pkg.Version).Last());

            foreach (var versionHistory in new List <PathAtom>[] { m_nugetFrameworkMonikers.FullFrameworkVersionHistory, m_nugetFrameworkMonikers.NetCoreVersionHistory })
            {
                FindAllCompatibleFrameworkMonikers(analyzedPackage, (List <PathAtom> monikers) =>
                {
                    if (monikers.Count == 0)
                    {
                        return;
                    }

                    if (analyzedPackage.IsNetStandardPackageOnly)
                    {
                        cases.AddRange(m_nugetFrameworkMonikers.NetStandardToFullFrameworkCompatibility.Select(m => new CaseClause(new LiteralExpression(m.ToString(m_pathTable.StringTable)))));
                    }

                    cases.AddRange(monikers.Take(monikers.Count - 1).Select(m => new CaseClause(new LiteralExpression(m.ToString(m_pathTable.StringTable)))));

                    var compile      = new List <IExpression>();
                    var runtime      = new List <IExpression>();
                    var dependencies = new List <IExpression>();

                    // Compile items
                    if (TryGetValueForFrameworkAndFallbacks(analyzedPackage.References, new NugetTargetFramework(monikers.First()), out IReadOnlyList <RelativePath> refAssemblies))
                    {
                        compile.AddRange(refAssemblies.Select(r => CreateSimpleBinary(r)));
                    }

                    // Runtime items
                    if (TryGetValueForFrameworkAndFallbacks(analyzedPackage.Libraries, new NugetTargetFramework(monikers.First()), out IReadOnlyList <RelativePath> libAssemblies))
                    {
                        runtime.AddRange(libAssemblies.Select(l => CreateSimpleBinary(l)));
                    }

                    // For full framework dependencies we unconditionally include all the distinct dependencies from the nuspec file,
                    // .NETStandard dependencies are only included if the moniker and the parsed target framework match!
                    if (m_nugetFrameworkMonikers.IsFullFrameworkMoniker(monikers.First()))
                    {
                        dependencies.AddRange(allFullFrameworkDeps.Select(dep => CreateImportFromForDependency(dep)));
                    }
                    else
                    {
                        if (analyzedPackage.DependenciesPerFramework.TryGetValue(monikers.First(), out IReadOnlyList <INugetPackage> dependencySpecificFrameworks))
                        {
                            dependencies.AddRange(dependencySpecificFrameworks.Select(dep => CreateImportFromForDependency(dep)));
                        }
                    }

                    cases.Add(
                        new CaseClause(
                            new LiteralExpression(monikers.Last().ToString(m_pathTable.StringTable)),
                            new ReturnStatement(
                                new CallExpression(
                                    PropertyAccess("Managed", "Factory", "createNugetPackage"),
                                    new LiteralExpression(analyzedPackage.Id),
                                    new LiteralExpression(analyzedPackage.Version),
                                    PropertyAccess("Contents", "all"),
                                    Array(compile),
                                    Array(runtime),
                                    m_nugetFrameworkMonikers.IsFullFrameworkMoniker(monikers.Last())
                                        ? Array(dependencies)
                                        : Array(new CallExpression(new Identifier("...addIfLazy"),
                                                                   new BinaryExpression(
                                                                       new PropertyAccessExpression("qualifier", "targetFramework"),
                                                                       SyntaxKind.EqualsEqualsEqualsToken,
                                                                       new LiteralExpression(monikers.First().ToString(m_pathTable.StringTable))
                                                                       ),
                                                                   new ArrowFunction(
                                                                       CollectionUtilities.EmptyArray <IParameterDeclaration>(),
                                                                       Array(dependencies)
                                                                       )
                                                                   ))
                                    )
                                )
                            )
                        );
                }, versionHistory);
            }

            return(cases);
        }
Example #13
0
        private List <ICaseClause> CreateSwitchCasesForTargetFrameworks(NugetAnalyzedPackage analyzedPackage, ITypeNode pkgType)
        {
            var cases = new List <ICaseClause>();

            Contract.Assert(analyzedPackage.TargetFrameworkWithFallbacks.Count != 0, "Managed package must have at least one target framework.");

            foreach (var framework in analyzedPackage.TargetFrameworkWithFallbacks)
            {
                // Emit the fallback cases first:
                foreach (var fallback in framework.Value)
                {
                    var fallbackString = fallback.ToString(m_pathTable.StringTable);
                    cases.Add(new CaseClause(new LiteralExpression(fallbackString)));
                }

                var compile      = new List <IExpression>();
                var runtime      = new List <IExpression>();
                var dependencies = new List <IExpression>();

                // Compile items
                if (TryGetValueForFrameworkAndFallbacks(analyzedPackage.References, new NugetTargetFramework(framework.Key), out IReadOnlyList <RelativePath> refAssemblies))
                {
                    foreach (var assembly in refAssemblies)
                    {
                        compile.Add(CreateSimpleBinary(assembly));
                    }
                }

                // Runtime items
                if (TryGetValueForFrameworkAndFallbacks(analyzedPackage.Libraries, new NugetTargetFramework(framework.Key), out IReadOnlyList <RelativePath> libAssemblies))
                {
                    foreach (var assembly in libAssemblies)
                    {
                        runtime.Add(CreateSimpleBinary(assembly));
                    }
                }

                // Dependency items
                if (analyzedPackage.DependenciesPerFramework.TryGetValue(
                        framework.Key,
                        out IReadOnlyList <INugetPackage> dependencySpecificFrameworks))
                {
                    foreach (var dependencySpecificFramework in dependencySpecificFrameworks)
                    {
                        dependencies.Add(CreateImportFromForDependency(dependencySpecificFramework));
                    }
                }

                dependencies.AddRange(analyzedPackage.Dependencies.Select(CreateImportFromForDependency));

                cases.Add(
                    new CaseClause(
                        new LiteralExpression(framework.Key.ToString(m_pathTable.StringTable)),
                        new ReturnStatement(
                            new CallExpression(
                                PropertyAccess("Managed", "Factory", "createNugetPackge"),
                                new LiteralExpression(analyzedPackage.Id),
                                new LiteralExpression(analyzedPackage.Version),
                                PropertyAccess("Contents", "all"),
                                Array(compile),
                                Array(runtime),
                                Array(dependencies)
                                )
                            )
                        )
                    );
            }

            return(cases);
        }
Example #14
0
 /// <summary>
 /// Returns true if a <paramref name="analyzedPackage"/> has at least one target framework.
 /// </summary>
 public static bool HasTargetFrameworks(this NugetAnalyzedPackage analyzedPackage)
 {
     return(analyzedPackage.TargetFrameworkWithFallbacks.Count != 0);
 }