private ExpressionList Visit(ExpressionList expressionList) { if (expressionList == null) return null; expressionList = expressionList.Clone(); for (int i = 0; i < expressionList.Count; i++) { expressionList[i] = Visit(expressionList[i]); } return expressionList; }
public virtual Differences VisitExpressionList(ExpressionList list1, ExpressionList list2, out ExpressionList changes, out ExpressionList deletions, out ExpressionList insertions){ changes = list1 == null ? null : list1.Clone(); deletions = list1 == null ? null : list1.Clone(); insertions = list1 == null ? new ExpressionList() : list1.Clone(); //^ assert insertions != null; Differences differences = new Differences(); for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){ //^ assert list2 != null; Expression nd2 = list2[j]; if (nd2 == null) continue; insertions.Add(null); } TrivialHashtable savedDifferencesMapFor = this.differencesMapFor; this.differencesMapFor = null; TrivialHashtable matchedNodes = new TrivialHashtable(); for (int i = 0, k = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; Expression nd1 = list1[i]; if (nd1 == null) continue; Differences diff; int j; Expression nd2 = this.GetClosestMatch(nd1, list1, list2, i, ref k, matchedNodes, out diff, out j); if (nd2 == null || diff == null){Debug.Assert(nd2 == null && diff == null); continue;} matchedNodes[nd1.UniqueKey] = nd1; matchedNodes[nd2.UniqueKey] = nd2; changes[i] = diff.Changes as Expression; deletions[i] = diff.Deletions as Expression; insertions[i] = diff.Insertions as Expression; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; } //Find deletions for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; Expression nd1 = list1[i]; if (nd1 == null) continue; if (matchedNodes[nd1.UniqueKey] != null) continue; changes[i] = null; deletions[i] = nd1; insertions[i] = null; differences.NumberOfDifferences += 1; } //Find insertions for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){ //^ assert list2 != null; Expression nd2 = list2[j]; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; insertions[n+j] = nd2; //Records nd2 as an insertion into list1, along with its position in list2 differences.NumberOfDifferences += 1; //REVIEW: put the size of the tree here? } if (differences.NumberOfDifferences == 0){ changes = null; deletions = null; insertions = null; } this.differencesMapFor = savedDifferencesMapFor; return differences; }
public virtual AttributeNode VisitAttributeNode(AttributeNode attribute, Node target) { if (attribute == null || target == null) return null; attribute.Constructor = this.VisitAttributeConstructor(attribute, target); ExpressionList expressions = attribute.Expressions = this.VisitExpressionList(attribute.Expressions); MemberBinding mb = attribute.Constructor as MemberBinding; if (mb == null || mb.BoundMember == null) { Debug.Assert(attribute.Constructor == null); return null; } //Check arguments for validity TypeNode attributeType = mb.BoundMember.DeclaringType; if (attributeType == null) return null; InstanceInitializer ctor = (InstanceInitializer)mb.BoundMember; ParameterList pars = ctor.Parameters; ExpressionList positionalArgs = new ExpressionList(); TrivialHashtable alreadySeenNames = new TrivialHashtable(); for (int i = 0, n = expressions == null ? 0 : expressions.Count; i < n; i++) { Expression e = expressions[i]; this.TypeInVariableContext(e as Literal); NamedArgument narg = e as NamedArgument; if (narg == null) { positionalArgs.Add(e); expressions[i] = null; continue; } if (narg.Name == null) { expressions[i] = null; continue; } if (alreadySeenNames[narg.Name.UniqueIdKey] != null) { this.HandleError(narg.Name, Error.DuplicateNamedAttributeArgument, narg.Name.ToString()); expressions[i] = null; continue; } alreadySeenNames[narg.Name.UniqueIdKey] = narg.Name; Member mem = null; TypeNode aType = attributeType; while (aType != null) { MemberList members = this.GetTypeView(aType).GetMembersNamed(narg.Name); for (int j = 0, m = members == null ? 0 : members.Count; j < m; j++) { mem = members[j]; if (mem == null) continue; switch (mem.NodeType) { case NodeType.Field: if (!mem.IsPublic) goto error; Field f = (Field)mem; if (f.IsInitOnly || f.IsLiteral || f.IsStatic) goto error; if (!this.IsValidTypeForCustomAttributeParameter(f.Type)) { this.HandleError(narg, Error.BadNamedAttributeArgumentType, this.GetMemberSignature(f)); this.HandleRelatedError(f); return null; } this.CheckForObsolesence(narg, f); narg.IsCustomAttributeProperty = false; e = this.typeSystem.ImplicitCoercion(narg.Value, narg.Type = f.Type, this.TypeViewer); if (!this.IsValidTypeForCustomAttributeArgument(e, narg.Value)) return null; if (e is BinaryExpression && e.NodeType == NodeType.Box) { narg.ValueIsBoxed = true; e = ((BinaryExpression)e).Operand1; } narg.Value = e; goto doneWithArg; case NodeType.Property: if (!mem.IsPublic) goto error; Property p = (Property)mem; if (!this.IsValidTypeForCustomAttributeParameter(p.Type)) { this.HandleError(narg, Error.BadNamedAttributeArgumentType, this.GetMemberSignature(p)); this.HandleRelatedError(p); return null; } if (p.Setter == null || p.Getter == null || p.IsStatic || !p.Setter.IsPublic || !p.Getter.IsPublic) goto error; this.CheckForObsolesence(narg, p); narg.IsCustomAttributeProperty = true; e = this.typeSystem.ImplicitCoercion(narg.Value, narg.Type = p.Type, this.TypeViewer); if (!this.IsValidTypeForCustomAttributeArgument(e, narg.Value)) return null; if (e is BinaryExpression && e.NodeType == NodeType.Box) { narg.ValueIsBoxed = true; e = ((BinaryExpression)e).Operand1; } narg.Value = e; goto doneWithArg; } } aType = aType.BaseType; } error: if (mem != null) { this.HandleError(narg, Error.BadNamedAttributeArgument, narg.Name.ToString()); this.HandleRelatedError(mem); } else this.HandleError(narg, Error.NoSuchMember, this.GetTypeName(attributeType), narg.Name.ToString()); doneWithArg: ; } ExpressionList exprs = positionalArgs.Clone(); this.CoerceArguments(pars, ref positionalArgs, true, ctor.CallingConvention); attribute.Expressions = positionalArgs; for (int i = 0, n = positionalArgs == null ? 0 : positionalArgs.Count; i < n; i++) { Expression e = positionalArgs[i]; if (e == null) continue; if (!this.IsValidTypeForCustomAttributeArgument(e, exprs[i])) return null; if (e is BinaryExpression && e.NodeType == NodeType.Box) e = ((BinaryExpression)e).Operand1; positionalArgs[i] = e; } for (int i = 0, n = expressions == null ? 0 : expressions.Count; i < n; i++) { Expression e = expressions[i]; if (e == null) continue; positionalArgs.Add(e); } attribute.Expressions = positionalArgs; //Now call specific visitors to deal with any pseudo custom attributes that describe metadata settings for target switch (target.NodeType) { case NodeType.Assembly: return this.VisitAssemblyAttribute(attribute, (AssemblyNode)target); case NodeType.Field: return this.VisitFieldAttribute(attribute, (Field)target); case NodeType.InstanceInitializer: case NodeType.StaticInitializer: case NodeType.Method: return this.VisitMethodAttribute(attribute, (Method)target); case NodeType.Property: return this.VisitPropertyAttribute(attribute, (Property)target); case NodeType.Parameter: return this.VisitParameterAttribute(attribute, (Parameter)target); default: TypeNode t = target as TypeNode; if (t != null) return this.VisitTypeAttribute(attribute, t); break; } return attribute; }