/// <summary> /// Handler of general containers. /// Moving upward from deepest container. /// /// $(name) or $(name:project) or $([MSBuild]::MakeRelative($(path1), ...):project) .. /// https://msdn.microsoft.com/en-us/library/vstudio/dd633440%28v=vs.120%29.aspx /// </summary> /// <param name="data"></param> /// <param name="sh"></param> /// <param name="limit">Limitation to containers. Aborts if reached</param> /// <exception cref="LimitException"></exception> /// <returns></returns> protected string containerIn(string data, StringHandler sh, uint limit) { Regex con = RPattern.ContainerInCompiled; int maxRep = 1; // rule of depth, e.g.: $(p1 = $(Platform))$(p2 = $(p1))$(p2) //TODO: it's slowest but fully compatible with classic rules with minimal programming.. so, improve performance references.Clear(); uint step = 0; do { if (step++ > limit) { sh.flush(); throw new LimitException("Restriction of supported containers '{0}' reached. Aborted.", limit); } data = con.Replace(data, delegate(Match m) { string raw = m.Groups[1].Value; Log.Trace("containerIn: raw - `{0}`", raw); return(evaluate(prepare(sh.recovery(raw)))); }, maxRep); // protect before new checking data = sh.protectEscContainer(sh.protectMixedQuotes(data)); } while(con.IsMatch(data)); return(data); }
/// <summary> /// Entry point to evaluating MSBuild data. /// </summary> /// <param name="data">mixed data</param> /// <returns>All evaluated values for data</returns> public virtual string parse(string data) { if (String.IsNullOrEmpty(data)) { return(String.Empty); // convert to not null value } if (String.IsNullOrWhiteSpace(data)) { return(data); // save all white-space characters } StringHandler sh = new StringHandler(); lock (_lock) { return(hquotes( sh.recovery( containerIn( sh.protectEscContainer( sh.protectMixedQuotes(data) ), sh, CONTAINERS_LIMIT ) ) )); } }