Example #1
0
        /// <summary>
        /// Processes the <c>composer.json</c> file.
        /// </summary>
        public override bool Execute()
        {
            // parse the input JSON file:
            JSONNode json;

            try
            {
                json = JSON.Parse(File.ReadAllText(ComposerJsonPath));
            }
            catch (JSONFormatException f)
            {
                LogError(ErrorCodes.ERR_SyntaxError, new Location {
                    Start = f.Position
                }, f.Message);
                return(false);
            }
            catch (Exception ex)
            {
                Log.LogErrorFromException(ex);
                return(false);
            }

            // cleanup output properties
            Authors                   = Array.Empty <ITaskItem>();
            Dependencies              = Array.Empty <ITaskItem>();
            Autoload_ClassMap         = Array.Empty <ITaskItem>();
            Autoload_ClassMap_Exclude = Array.Empty <ITaskItem>();
            Autoload_PSR4             = Array.Empty <ITaskItem>();
            Autoload_Files            = Array.Empty <ITaskItem>();

            // process the file:
            foreach (var node in json)
            {
                switch (node.Key.ToLowerInvariant())
                {
                case "name":
                    Name = GetName(node.Value);
                    break;

                case "description":
                    Description = GetDescription(node.Value);
                    break;

                case "keywords":
                    Tags = GetTags(node.Value);
                    break;

                case "homepage":
                    Homepage = GetHomepage(node.Value);
                    break;

                case "license":
                    License = SpdxHelpers.SanitizeSpdx(node.Value, out var spdxwarning);
                    if (spdxwarning != null)
                    {
                        LogError(ErrorCodes.WRN_SPDX, node.Value.Location, spdxwarning);
                    }
                    break;

                case "version":
                    /*
                     * Note, in general it is recommended to omit this tag and infer the value from a build process.
                     * Anyways, if it's there we should respect it.
                     */

                    /*
                     * This must follow the format of `X.Y.Z` or `vX.Y.Z`
                     * with an optional suffix of `-dev`, `-patch` (-p), `-alpha` (-a), `-beta` (-b) or `-RC`.
                     * The patch, alpha, beta and RC suffixes can also be followed by a number.
                     */
                    Version = SanitizeVersionValue(node.Value.Value);
                    break;

                case "time":
                    ReleaseDate = GetReleaseDate(node.Value);
                    break;

                case "authors":
                    Authors = Authors.Concat(GetAuthors(node.Value.AsArray)).AsArray();
                    break;

                case "require":
                    // { "name": "version constraint", }
                    Dependencies = Dependencies.Concat(GetDependencies(node.Value)).AsArray();
                    break;

                case "require-dev":
                    if (ComposerIncludeDevPackages)
                    {
                        // { "name": "version constraint", }
                        Dependencies = Dependencies.Concat(GetDependencies(node.Value)).AsArray();
                    }
                    break;

                case "suggest":
                    if (ComposerIncludeSuggestPackages)
                    {
                        // CONSIDER: Suggest packages are only informative, does not make much sense to reference those "names" directly.

                        // { "name": "description", }
                        Dependencies = Dependencies.Concat(GetDependencies(node.Value, ignoreVersion: true)).AsArray();
                    }
                    break;

                case "autoload":
                    // "autoload" : { "psr-0", "psr-4", "classmap", "exclude-from-classmap", "files" }
                    foreach (var autoload in node.Value)
                    {
                        switch (autoload.Key.ToLowerInvariant())
                        {
                        case "psr-4":
                            Autoload_PSR4 = Autoload_PSR4.Concat(GetAutoloadPsr4FromPsr4(autoload.Value.AsObject)).AsArray();
                            break;

                        case "psr-0":
                            Autoload_PSR4 = Autoload_PSR4.Concat(GetAutoloadPsr4FromPsr0(autoload.Value.AsObject)).AsArray();
                            break;

                        case "classmap":
                            Autoload_ClassMap = Autoload_ClassMap.Concat(
                                GetAutoloadClassMapString(autoload.Value.AsArray, false).Select(path => new TaskItem(path))).ToArray();
                            break;

                        case "exclude-from-classmap":
                            Autoload_ClassMap_Exclude = Autoload_ClassMap_Exclude.Concat(
                                GetAutoloadClassMapString(autoload.Value.AsArray, true).Select(path => new TaskItem(path))).ToArray();
                            break;

                        case "files":
                            if (autoload.Value is JSONArray files_array)
                            {
                                Autoload_Files = Autoload_Files.Concat(
                                    files_array
                                    .Select(node => node.Value?.Trim())
                                    .Where(str => !string.IsNullOrEmpty(str))
                                    .Select(path => new TaskItem(path))).ToArray();
                            }
                            break;

                        default:
                            // ???
                            LogError(ErrorCodes.WRN_Unhandled, node.Value.Location, $"autoload \"{autoload.Key}\" key is not handled.");
                            break;
                        }
                    }

                    break;
                }
            }

            return(true);
        }