bool EvaluateReference(string str, List <MSBuildItemEvaluated> evaluatedItemsCollection, ref int i, out object val, out bool needsItemEvaluation)
        {
            needsItemEvaluation = false;

            val = null;
            var tag   = str[i];
            int start = i;

            i += 2;
            int j = FindClosingChar(str, i, ')');

            if (j == -1)
            {
                val = StringInternPool.AddShared(str, start, str.Length - start);
                i   = str.Length;
                return(false);
            }

            string prop = StringInternPool.AddShared(str, i, j - i).Trim();

            i = j + 1;

            bool res = false;

            if (prop.Length > 0)
            {
                switch (tag)
                {
                case '$': {
                    bool nie;
                    res = EvaluateProperty(prop, evaluatedItemsCollection != null, out val, out nie);
                    needsItemEvaluation |= nie;
                    break;
                }

                case '%': res = EvaluateMetadata(prop, out val); break;

                case '@':
                    if (evaluatedItemsCollection != null)
                    {
                        res = EvaluateList(prop, evaluatedItemsCollection, out val);
                    }
                    else
                    {
                        res = false;
                        needsItemEvaluation = true;
                    }
                    break;
                }
            }
            if (!res)
            {
                val = StringInternPool.AddShared(str, start, j - start + 1);
            }

            return(res);
        }
        string Evaluate(string str, StringBuilder sb, List <MSBuildItemEvaluated> evaluatedItemsCollection, out bool needsItemEvaluation)
        {
            needsItemEvaluation = false;

            if (str == null)
            {
                return(null);
            }
            int i = FindNextTag(str, 0);

            if (i == -1)
            {
                return(str);
            }

            int last = 0;

            if (sb == null)
            {
                sb = GetEvaluationSb();
            }

            try {
                do
                {
                    sb.Append(str, last, i - last);
                    int    j = i;
                    object val;
                    bool   nie;
                    if (!EvaluateReference(str, evaluatedItemsCollection, ref j, out val, out nie))
                    {
                        allResolved = false;
                    }
                    needsItemEvaluation |= nie;
                    sb.Append(ValueToString(val));
                    last = j;

                    i = FindNextTag(str, last);
                }while (i != -1);

                sb.Append(str, last, str.Length - last);
                return(StringInternPool.AddShared(sb));
            } finally {
                evaluationSbs.Enqueue(sb);
            }
        }
Пример #3
0
        public static object ConsumeUntilNewLine(ref object ws)
        {
            if (ws == null)
            {
                return(null);
            }

            var s = ws as string;

            if (s != null)
            {
                for (int n = s.Length - 1; n >= 0; n--)
                {
                    var c = s [n];
                    if (c == '\r' || c == '\n')
                    {
                        if (n == s.Length - 1)
                        {
                            break;                             // Default case, consume the whole string
                        }
                        int    len = n + 1;
                        string res = StringInternPool.AddShared(s, 0, len);
                        ws = StringInternPool.AddShared(s, len, s.Length - len);
                        return(res);
                    }
                }
                var result = ws;
                ws = null;
                return(result);
            }
            var sb = ws as StringBuilder;

            if (sb != null)
            {
                for (int n = sb.Length - 1; n >= 0; n--)
                {
                    var c = sb [n];
                    if (c == '\r' || c == '\n')
                    {
                        if (n == sb.Length - 1)
                        {
                            break;                             // Default case, consume the whole string
                        }
                        var res = sb.ToString(0, n + 1);
                        sb.Remove(0, n + 1);
                        return(res);
                    }
                }
                string result = StringInternPool.AddShared(sb);
                ws = null;
                return(result);
            }

            // It's a MSBuildWhitespace

            var mw = (MSBuildWhitespace)ws;

            mw.GenerateStrings();

            var toSplit = mw.FindLastWithNewLine();

            if (toSplit == null)
            {
                var result = ws;
                ws = null;
                return(result);
            }
            else
            {
                var remaining = toSplit.content;
                var result    = ConsumeUntilNewLine(ref remaining);

                // Set the remaining value

                if (toSplit.next == null)
                {
                    // New line found in last node. The remaining is just the split string
                    ws = remaining;
                }
                else
                {
                    if (remaining == null)
                    {
                        return(toSplit.next);                        // Consumed the whole string of this node. The remaining is the next node
                    }
                    // New line found in the middle of the chain. A new node with the remaining has to be created
                    ws = new MSBuildWhitespace {
                        content = remaining,
                        next    = toSplit.next
                    };
                }

                // Generate the consumed value

                if (toSplit != mw)
                {
                    // New line found in the middle of the chain. Update the node content and split the chain.
                    toSplit.content = result;
                    toSplit.next    = null;
                    return(mw);
                }
                else
                {
                    // New line found in first node. The result is just the consumed string. Nothing else to do.
                    return(result);
                }
            }
        }