Esempio n. 1
0
        public Dictionary <string, string> GetCodeFiles()
        {
            Dictionary <string, string> output = new Dictionary <string, string>();
            string fileExtension = ProgrammingLanguageParser.LangToFileExtension(this.RootProgrammingLanguage);

            foreach (ProjectFilePath sourceDir in this.SourceFolders)
            {
                string[] files = FileUtil.GetAllAbsoluteFilePathsDescendentsOf(sourceDir.AbsolutePath);
                foreach (string filepath in files)
                {
                    if (filepath.ToLowerInvariant().EndsWith(fileExtension))
                    {
                        string relativePath = FileUtil.ConvertAbsolutePathToRelativePath(
                            filepath,
                            this.ProjectDirectory);
                        output[relativePath] = FileUtil.ReadFileText(filepath);
                    }
                }
            }
            return(output);
        }
Esempio n. 2
0
        public static BuildContext Parse(
            string projectDir,
            string buildFile,
            string nullableTargetName,
            IList <Wax.BuildArg> buildArgOverrides,
            IList <Wax.ExtensionArg> extensionArgOverrides)
        {
            BuildRoot buildInput = GetBuildRoot(buildFile, projectDir);

            Dictionary <string, Target> targetsByName = new Dictionary <string, Target>();

            foreach (Target target in buildInput.Targets)
            {
                string name = target.Name;
                if (name == null)
                {
                    throw new InvalidOperationException("A target in the build file is missing a name.");
                }
                if (targetsByName.ContainsKey(name))
                {
                    throw new InvalidOperationException("There are multiple build targets with the name '" + name + "'.");
                }
                targetsByName[name] = target;
            }

            List <Wax.BuildArg>     buildArgs     = new List <Wax.BuildArg>();
            List <Wax.ExtensionArg> extensionArgs = new List <Wax.ExtensionArg>();
            List <BuildVar>         buildVars     = new List <BuildVar>();

            List <BuildItem> buildItems = new List <BuildItem>();

            if (nullableTargetName == null)
            {
                buildItems.Add(buildInput);
            }
            else
            {
                HashSet <string> targetsVisited = new HashSet <string>();
                string           nextItem       = nullableTargetName;
                Target           walker;
                while (nextItem != null)
                {
                    if (targetsVisited.Contains(nextItem))
                    {
                        throw new InvalidOperationException("Build target inheritance loop for '" + nextItem + "' contains a cycle.");
                    }
                    targetsVisited.Add(nextItem);
                    if (!targetsByName.ContainsKey(nextItem))
                    {
                        throw new InvalidOperationException("There is no build target named: '" + nextItem + "'.");
                    }
                    walker = targetsByName[nextItem];
                    buildItems.Add(walker);
                    nextItem = walker.InheritFrom;
                }
                buildItems.Add(buildInput);
            }

            buildItems.Reverse(); // The attributes in the leaf node have precedence.

            foreach (BuildItem currentItem in buildItems)
            {
                buildArgs.AddRange(currentItem.BuildArgs);
                extensionArgs.AddRange(currentItem.ExtensionArgs);
                buildVars.AddRange(currentItem.BuildVars);
            }

            if (buildArgOverrides != null)
            {
                buildArgs.AddRange(buildArgOverrides);
            }
            if (extensionArgOverrides != null)
            {
                extensionArgs.AddRange(extensionArgOverrides);
            }

            PercentReplacer pr = new PercentReplacer()
                                 .AddReplacement("TARGET_NAME", nullableTargetName ?? "");

            // Do a first pass over all the build args to fetch anything that is used by %PERCENT_REPLACEMENT% and anything
            // that can be defined with multiple values in a list.
            List <string>       sources             = new List <string>();
            List <string>       icons               = new List <string>();
            string              version             = "1.0";
            Locale              compilerLocale      = Locale.Get("en");
            string              projectId           = null;
            ProgrammingLanguage programmingLanguage = ProgrammingLanguage.CRAYON;
            List <Wax.BuildArg> remainingBuildArgs  = new List <Wax.BuildArg>();
            List <string>       envFilesBuilder     = new List <string>();
            List <string>       deps = new List <string>();

            foreach (Wax.BuildArg buildArg in buildArgs)
            {
                switch (buildArg.Name)
                {
                case "programmingLanguage":
                    ProgrammingLanguage?pl = ProgrammingLanguageParser.Parse(buildArg.Value);
                    if (pl == null)
                    {
                        throw new InvalidOperationException("Invalid programming language in build file: '" + buildArg.Value + "'.");
                    }
                    programmingLanguage = pl.Value;
                    break;

                case "version":
                    version = buildArg.Value;
                    break;

                case "source":
                    sources.Add(buildArg.Value);
                    break;

                case "icon":
                    icons.Add(buildArg.Value);
                    break;

                case "compilerLocale":
                    compilerLocale = Locale.Get(buildArg.Value);
                    break;

                case "id":
                    projectId = buildArg.Value;
                    break;

                case "dependencies":
                    deps.Add(buildArg.Value);
                    break;

                case "envFile":
                    throw new Exception();     // These are eliminated in the parsing phase.

                default:
                    remainingBuildArgs.Add(buildArg);
                    break;
                }
            }

            if (projectId == null)
            {
                throw new InvalidOperationException("The projectId is not defined in the build file.");
            }
            if (projectId.Length == 0)
            {
                throw new InvalidOperationException("projectId cannot be blank.");
            }
            if (projectId.ToCharArray().Any(c => (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9')))
            {
                throw new InvalidOperationException("projectId can only contain alphanumeric characters.");
            }
            if (projectId[0] >= '0' && projectId[0] <= '9')
            {
                throw new InvalidOperationException("projectId cannot being with a number.");
            }

            pr
            .AddReplacement("PROJECT_ID", projectId)
            .AddReplacement("COMPILER_LANGUAGE", programmingLanguage.ToString().ToUpperInvariant())
            .AddReplacement("VERSION", version)
            .AddReplacement("COMPILER_LOCALE", compilerLocale.ID.ToLowerInvariant());

            ProjectFilePath[] envFiles = ToFilePaths(projectDir, envFilesBuilder);

            BuildContext buildContext = new BuildContext()
            {
                ProjectID               = projectId,
                ProjectDirectory        = projectDir,
                SourceFolders           = ToFilePaths(projectDir, sources),
                Version                 = version,
                RootProgrammingLanguage = programmingLanguage,
                IconFilePaths           = icons
                                          // TODO: icon values should be concatenated within a build target, but override previous targets
                                          .Select(t => pr.Replace(t))
                                          .Select(t => FileUtil.GetAbsolutePathFromRelativeOrAbsolutePath(projectDir, t))
                                          .Select(t => FileUtil.GetCanonicalizeUniversalPath(t))
                                          .Where(t =>
                {
                    if (!System.IO.File.Exists(t))
                    {
                        throw new System.InvalidOperationException("The following icon path does not exist: '" + t + "'.");
                    }
                    return(true);
                })
                                          .ToArray(),
                CompilerLocale = compilerLocale,
                LocalDeps      = deps
                                 .Select(t => Wax.Util.EnvironmentVariables.DoReplacementsInString(t))
                                 .Select(t => pr.Replace(t))
                                 .Select(t => FileUtil.GetCanonicalizeUniversalPath(t))
                                 .ToArray(),
                ExtensionArgs = extensionArgs.Select(arg => { arg.Value = pr.Replace(arg.Value); return(arg); }).ToArray(),
            };

            foreach (Wax.BuildArg buildArg in remainingBuildArgs)
            {
                string value = pr.Replace(buildArg.Value);
                switch (buildArg.Name)
                {
                case "title": buildContext.ProjectTitle = pr.Replace(value); break;

                case "description": buildContext.Description = pr.Replace(value); break;

                case "orientation": buildContext.Orientation = ParseOrientations(value); break;

                case "output": buildContext.OutputFolder = FileUtil.JoinAndCanonicalizePath(projectDir, pr.Replace(value)); break;

                case "delegateMainTo": buildContext.DelegateMainTo = value; break;

                case "removeSymbols": buildContext.RemoveSymbols = GetBoolValue(value); break;

                case "skipRun": buildContext.SkipRun = GetBoolValue(value); break;
                }
            }

            Dictionary <string, BuildVar> buildVarLookup = new Dictionary <string, BuildVar>();

            foreach (BuildVar bv in buildVars)
            {
                buildVarLookup[bv.ID] = bv;
            }
            buildContext.BuildVariableLookup = buildVarLookup;

            return(buildContext);
        }