public virtual Differences VisitTypeNodeList(TypeNodeList list1, TypeNodeList list2,
   out TypeNodeList changes, out TypeNodeList deletions, out TypeNodeList insertions){
   changes = list1 == null ? null : list1.Clone();
   deletions = list1 == null ? null : list1.Clone();
   insertions = list1 == null ? new TypeNodeList() : list1.Clone();
   //^ assert insertions != null;
   Differences differences = new Differences();
   //Compare definitions that have matching key attributes
   TrivialHashtable matchingPosFor = new TrivialHashtable();
   TrivialHashtable matchedNodes = new TrivialHashtable();
   for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){
     //^ assert list2 != null;
     TypeNode nd2 = list2[j];
     if (nd2 == null || nd2.Name == null) continue;
     string fullName = nd2.FullName;
     if (fullName == null) continue;
     matchingPosFor[Identifier.For(fullName).UniqueIdKey] = j;
     insertions.Add(null);
   }
   for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){
     //^ assert list1 != null && changes != null && deletions != null;
     TypeNode nd1 = list1[i];
     if (nd1 == null || nd1.Name == null) continue;
     string fullName = nd1.FullName;
     if (fullName == null) continue;
     object pos = matchingPosFor[Identifier.For(fullName).UniqueIdKey];
     if (!(pos is int)) continue;
     //^ assert pos != null;
     //^ assume list2 != null; //since there was entry int matchingPosFor
     int j = (int)pos;
     TypeNode nd2 = list2[j];
     //^ assume nd2 != null;
     //nd1 and nd2 have the same key attributes and are therefore treated as the same entity
     matchedNodes[nd1.UniqueKey] = nd1;
     matchedNodes[nd2.UniqueKey] = nd2;
     //nd1 and nd2 may still be different, though, so find out how different
     Differences diff = this.VisitTypeNode(nd1, nd2);
     if (diff == null){Debug.Assert(false); continue;}
     if (diff.NumberOfDifferences != 0){
       changes[i] = diff.Changes as TypeNode;
       deletions[i] = diff.Deletions as TypeNode;
       insertions[i] = diff.Insertions as TypeNode;
       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;
       if (nd1.DeclaringModule == this.OriginalModule || 
         (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){
         if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList();
         this.MembersThatHaveChanged.Add(nd1);
       }
       continue;
     }
     changes[i] = null;
     deletions[i] = null;
     insertions[i] = null;
     insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation
   }
   //Find deletions
   for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){
     //^ assert list1 != null && changes != null && deletions != null;
     TypeNode 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;
     if (nd1.DeclaringModule == this.OriginalModule || 
       (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){
       if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList();
       this.MembersThatHaveChanged.Add(nd1);
     }
   }
   //Find insertions
   for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){
     //^ assert list2 != null;
     TypeNode 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;
   }
   return differences;
 }
示例#2
0
 private InterfaceList ParseInterfaceList(TokenSet followers, bool expectLeftBrace){
   InterfaceList ilist = new InterfaceList();
   TokenSet followersOrComma = followers|Token.Comma;
   for(;;){
     Expression id = this.scanner.GetIdentifier();
     switch(this.currentToken){
       case Token.Bool:
       case Token.Decimal:
       case Token.Sbyte:
       case Token.Byte:
       case Token.Short:
       case Token.Ushort:
       case Token.Int:
       case Token.Uint:
       case Token.Long:
       case Token.Ulong:
       case Token.Char:
       case Token.Float:
       case Token.Double:
       case Token.Object:
       case Token.String:
       case Token.Void:
         TypeExpression texpr = this.TypeExpressionFor(this.currentToken);
         this.GetNextToken();
         ilist.Add(new InterfaceExpression(texpr.Expression, texpr.SourceContext));
         goto lookForComma;
       default:
         bool idOK = Parser.IdentifierOrNonReservedKeyword[this.currentToken];
         if (idOK){
           this.GetNextToken();
           if (this.currentToken == Token.DoubleColon){
             this.GetNextToken();
             Identifier id2 = this.scanner.GetIdentifier();
             id2.Prefix = (Identifier)id;
             id2.SourceContext.StartPos = id.SourceContext.StartPos;
             this.SkipIdentifierOrNonReservedKeyword();
             id = id2;
           }
           if (this.currentToken == Token.Dot)
             id = this.ParseQualifiedIdentifier(id, followersOrComma|Token.LessThan);
         }else{
           int col = this.scanner.endPos;
           this.SkipIdentifierOrNonReservedKeyword(Error.TypeExpected);
           if (col == this.scanner.endPos && this.currentToken != Token.EndOfFile){
             //Did not consume a token, but just gave an error
             if (!followersOrComma[this.currentToken]) this.GetNextToken();
             if (followers[this.currentToken]) return ilist;
             if (this.currentToken != Token.Comma){
               if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) continue;
               break;
             }
             this.GetNextToken();
             continue;
           }
           if (this.currentToken == Token.Dot)
             id = this.ParseQualifiedIdentifier(id, followersOrComma|Token.LessThan);
           if (!idOK) goto lookForComma;
         }
         break;
     }
     //I really want an Identifier here for StartName
     if (this.sink != null) {
       Identifier name = id as Identifier;
       if (id is QualifiedIdentifier) {
         name = ((QualifiedIdentifier)id).Identifier;
       }
       if (name != null) {
         this.sink.StartName(name);
       }
     }
     InterfaceExpression ifaceExpr = new InterfaceExpression(id, id.SourceContext);
     if (this.currentToken == Token.LessThan){
     yetAnotherTypeArgumentList:
       this.GetNextToken();
       TypeNodeList arguments = new TypeNodeList();
       for(;;){
         TypeNode t = this.ParseTypeExpression(null, followers|Token.Comma|Token.GreaterThan);
         arguments.Add(t);
         if (this.currentToken != Token.Comma) break;
         this.GetNextToken();
       }
       ifaceExpr.TemplateArguments = arguments;
       ifaceExpr.TemplateArgumentExpressions = arguments.Clone();
       ifaceExpr.SourceContext.EndPos = this.scanner.endPos;
       this.Skip(Token.GreaterThan);
       if (this.currentToken == Token.Dot) {
         TemplateInstance tempInst = new TemplateInstance(ifaceExpr.Expression, ifaceExpr.TemplateArguments);
         tempInst.TypeArgumentExpressions = ifaceExpr.TemplateArguments == null ? null : ifaceExpr.TemplateArguments.Clone();
         tempInst.SourceContext = ifaceExpr.SourceContext;
         ifaceExpr.Expression = this.ParseQualifiedIdentifier(tempInst, followersOrComma|Token.LessThan);
         ifaceExpr.TemplateArguments = null;
         ifaceExpr.TemplateArgumentExpressions = null;
         if (ifaceExpr.Expression != null) ifaceExpr.SourceContext = ifaceExpr.Expression.SourceContext;
         if (this.currentToken == Token.LessThan) goto yetAnotherTypeArgumentList;
       }
     }
     ilist.Add(ifaceExpr);
   lookForComma:
     if (Parser.TypeOperator[this.currentToken] && !(expectLeftBrace && this.currentToken == Token.LeftBrace)){
       this.HandleError(Error.BadBaseType);
       this.GetNextToken();
       if (this.currentToken == Token.RightBracket || this.currentToken == Token.RightBrace)
         this.GetNextToken();
       this.SkipTo(followersOrComma, Error.None);
     }else if (!followersOrComma[this.currentToken])
       this.SkipTo(followersOrComma, Error.TypeExpected);
     if (this.currentToken == Token.Comma){
       if (followers[Token.Comma] && followers[Token.GreaterThan])
         break; //Parsing the constraint of a type parameter
       this.GetNextToken();
       if (expectLeftBrace && (this.currentToken == Token.Class || this.currentToken == Token.Struct || this.currentToken == Token.New))
         break;
     }else if (!Parser.TypeStart[this.currentToken] || this.currentToken == Token.Where)
       break;
     else if (Parser.ContractStart[this.currentToken])
       break;
   }
   return ilist;
 }