+
+ a_names = [call.functionName for call in self.a[alo:ahi]]
+ b_names = [call.functionName for call in self.b[blo:bhi]]
+
+ matcher = difflib.SequenceMatcher(None, a_names, b_names)
+ for tag, _alo, _ahi, _blo, _bhi in matcher.get_opcodes():
+ _alo += alo
+ _ahi += alo
+ _blo += blo
+ _bhi += blo
+ if tag == 'replace':
+ self.replace_dissimilar(_alo, _ahi, _blo, _bhi)
+ elif tag == 'delete':
+ self.delete(_alo, _ahi, _blo, _bhi)
+ elif tag == 'insert':
+ self.insert(_alo, _ahi, _blo, _bhi)
+ elif tag == 'equal':
+ self.replace_similar(_alo, _ahi, _blo, _bhi)
+ else:
+ raise ValueError, 'unknown tag %s' % (tag,)
+
+ def replace_similar(self, alo, ahi, blo, bhi):
+ assert alo < ahi and blo < bhi
+ assert ahi - alo == bhi - blo
+ for i in xrange(0, bhi - blo):
+ self.highlighter.write('| ')
+ a_call = self.a[alo + i]
+ b_call = self.b[blo + i]
+ assert a_call.functionName == b_call.functionName
+ self.dumpCallNos(a_call.no, b_call.no)
+ self.highlighter.bold(True)
+ self.highlighter.write(b_call.functionName)
+ self.highlighter.bold(False)
+ self.highlighter.write('(')
+ sep = ''
+ numArgs = max(len(a_call.args), len(b_call.args))
+ for j in xrange(numArgs):
+ self.highlighter.write(sep)
+ try:
+ a_arg = a_call.args[j]
+ except IndexError:
+ pass
+ try:
+ b_arg = b_call.args[j]
+ except IndexError:
+ pass
+ self.replace_value(a_arg, b_arg)
+ sep = ', '
+ self.highlighter.write(')')
+ if a_call.ret is not None or b_call.ret is not None:
+ self.highlighter.write(' = ')
+ self.replace_value(a_call.ret, b_call.ret)
+ self.highlighter.write('\n')
+
+ def replace_dissimilar(self, alo, ahi, blo, bhi):
+ assert alo < ahi and blo < bhi