Ejemplo n.º 1
0
        public override void Visit(IArrayIndexer arrayIndexer)
        {
            if (arrayIndexer.Indices.Count() == 1 && Names.NameTable.ContainsKey(arrayIndexer.IndexedObject))
            {
                // the array expression, e.g.: this.array
                var arrayName = Names.NameTable[arrayIndexer.IndexedObject];
                // the contents expression, e.g.: this.array[..]
                var arrayContents = NameBuilder.FormElementsExpression(arrayName);

                // mark array indexes as compatible
                var index = arrayIndexer.Indices.First();
                if (Names.NameTable.ContainsKey(index))
                {
                    // The array reference may not have been used in a comparable way yet.
                    if (!ids.ContainsKey(arrayContents))
                    {
                        ids.Add(arrayContents, comparability.AddElement());
                    }

                    if (!collectionIndexes.ContainsKey(arrayContents))
                    {
                        collectionIndexes.Add(arrayContents, new HashSet <string>());
                    }

                    if (collectionIndexes[arrayContents].Add(Names.NameTable[index]))
                    {
                        // we haven't seen this index before, so re-mark indexes
                        Mark(collectionIndexes[arrayContents]);
                    }
                }

                PropogateTypeReference(arrayIndexer.IndexedObject, arrayIndexer);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// If the method call is a call to a Dictionary method, update the comparability information
        /// for keys and values.
        /// </summary>
        /// <remarks>
        ///   This uses <c>Key</c> and <c>Value</c> instead of <c>Keys</c> and <c>Values</c> since the declaration
        ///   printer uses <c>Key</c> and <c>Value</c> (it grabs it from the dictionary entry, as
        /// </remarks>
        /// <param name="call">the method call</param>
        private void HandleDictionaryMethod(IMethodCall call)
        {
            var receiver = call.ThisArgument;
            var callee   = call.MethodToCall.ResolvedMethod;

            var keys   = new List <IExpression>();
            var values = new List <IExpression>();

            var genericDef = TypeHelper.UninstantiateAndUnspecialize(receiver.Type);

            if (TypeHelper.TypesAreEquivalent(genericDef, Host.PlatformType.SystemCollectionsGenericDictionary, true))
            {
                if (callee.Name.Value.OneOf("Remove", "TryGetValue", "ContainsKey", "set_Item", "get_Item"))
                {
                    keys.Add(call.Arguments.First());
                }
                else if (callee.Name.Value.OneOf("Add"))
                {
                    keys.Add(call.Arguments.ElementAt(0));
                    values.Add(call.Arguments.ElementAt(1));
                }
            }

            var collectionName = Names.NameTable[receiver];
            var xs             = new [] {
                Tuple.Create(collectionName + ".Keys", keys),
                Tuple.Create(NameBuilder.FormElementsExpression(collectionName) + ".Key", keys),
                Tuple.Create(collectionName + ".Values", values),
                Tuple.Create(NameBuilder.FormElementsExpression(collectionName) + ".Value", values)
            };

            foreach (var x in xs.Where(c => c.Item2.Count > 0))
            {
                // The collection reference may not have been used in a comparable way yet.
                if (!ids.ContainsKey(x.Item1))
                {
                    ids.Add(x.Item1, comparability.AddElement());
                }

                var names = new List <string>();
                names.Add(x.Item1);
                names.AddRange(Names.Names(x.Item2));
                Mark(names);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// If the call is to a standard collection method, update the element and index comparability information
        /// </summary>
        /// <param name="call">the method call</param>
        private void HandleCollectionMethod(IMethodCall call)
        {
            var receiver = call.ThisArgument;
            var callee   = call.MethodToCall.ResolvedMethod;

            IExpression index    = null;
            var         elements = new List <IExpression>();

            foreach (var m in MemberHelper.GetImplicitlyImplementedInterfaceMethods(callee))
            {
                var genericDef = TypeHelper.UninstantiateAndUnspecialize(m.ContainingTypeDefinition);

                // IEnumerable does not define any methods that affect comparability

                // ICollection
                if (TypeHelper.TypesAreEquivalent(genericDef, Host.PlatformType.SystemCollectionsGenericICollection, true))
                {
                    if (m.Name.Value.OneOf("Add", "Remove", "Contains"))
                    {
                        elements.Add(call.Arguments.First());
                    }
                }

                // IList
                if (TypeHelper.TypesAreEquivalent(genericDef, Host.PlatformType.SystemCollectionsGenericIList, true))
                {
                    if (m.Name.Value.OneOf("IndexOf"))
                    {
                        elements.Add(call.Arguments.First());
                    }
                    else if (m.Name.Value.OneOf("get_Item", "set_Item", "RemoveAt"))
                    {
                        index = call.Arguments.First();
                    }
                    else if (m.Name.Value.OneOf("Insert"))
                    {
                        index = call.Arguments.ElementAt(0);
                        elements.Add(call.Arguments.ElementAt(1));
                    }
                }
            }

            if (index != null && Names.NameTable.ContainsKey(index))
            {
                var collectionName     = Names.NameTable[receiver];
                var collectionContents = NameBuilder.FormElementsExpression(collectionName);

                // The collection reference may not have been used in a comparable way yet.
                if (!ids.ContainsKey(collectionContents))
                {
                    ids.Add(collectionContents, comparability.AddElement());
                }

                if (!collectionIndexes.ContainsKey(collectionContents))
                {
                    collectionIndexes.Add(collectionContents, new HashSet <string>());
                }

                if (collectionIndexes[collectionContents].Add(Names.NameTable[index]))
                {
                    // we haven't seen this index before, so re-mark indexes
                    Mark(collectionIndexes[collectionContents]);
                }
            }

            if (elements.Count > 0)
            {
                var collectionName     = Names.NameTable[receiver];
                var collectionContents = NameBuilder.FormElementsExpression(collectionName);

                // The collection reference may not have been used in a comparable way yet.
                if (!ids.ContainsKey(collectionContents))
                {
                    ids.Add(collectionContents, comparability.AddElement());
                }

                var names = new List <string>();
                names.Add(collectionContents);
                names.AddRange(Names.Names(elements));
                Mark(names);
            }
        }