196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Projectpackage jdiff; 296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Projectimport java.util.*; 496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project/** 696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * This class contains method to compare two API objects. 796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * The differences are stored in an APIDiff object. 896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * See the file LICENSE.txt for copyright details. 1096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * @author Matthew Doar, mdoar@pobox.com 1196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 1296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Projectpublic class APIComparator { 1396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 1496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 1596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Top-level object representing the differences between two APIs. 1696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * It is this object which is used to generate the report later on. 1796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 1896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public APIDiff apiDiff; 1996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 2096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 2196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Package-level object representing the differences between two packages. 2296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * This object is also used to determine which file to write documentation 2396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * differences into. 2496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 2596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public PackageDiff pkgDiff; 2696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 2796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** Default constructor. */ 2896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public APIComparator() { 2996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff = new APIDiff(); 3096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 3196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 3296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** For easy local access to the old API object. */ 3396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project private static API oldAPI_; 3496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** For easy local access to the new API object. */ 3596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project private static API newAPI_; 3696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 3796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 3896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare two APIs. 3996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 4096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public void compareAPIs(API oldAPI, API newAPI) { 4196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("JDiff: comparing the old and new APIs ..."); 4296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldAPI_ = oldAPI; 4396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newAPI_ = newAPI; 4496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 4596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project double differs = 0.0; 4696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 4796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff.oldAPIName_ = oldAPI.name_; 4896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff.newAPIName_ = newAPI.name_; 4996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 5096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(oldAPI.packages_); 5196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(newAPI.packages_); 5296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 5396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find packages which were removed in the new API 5496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = oldAPI.packages_.iterator(); 5596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 5696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project PackageAPI oldPkg = (PackageAPI)(iter.next()); 5796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // This search is looking for an *exact* match. This is true in 5896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // all the *API classes. 5996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(newAPI.packages_, oldPkg); 6096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 6196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // If there an instance of a package with the same name 6296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // in both the old and new API, then treat it as changed, 6396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // rather than removed and added. There will never be more than 6496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // one instance of a package with the same name in an API. 6596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int existsNew = newAPI.packages_.indexOf(oldPkg); 6696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (existsNew != -1) { 6796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Package by the same name exists in both APIs 6896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // but there has been some or other change. 6996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 2.0 * comparePackages(oldPkg, (PackageAPI)(newAPI.packages_.get(existsNew))); 7096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 7196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 7296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Package " + oldPkg.name_ + " was removed"); 7396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff.packagesRemoved.add(oldPkg); 7496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 1.0; 7596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 7696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 7796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // The package exists unchanged in name or doc, but may 7896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // differ in classes and their members, so it still needs to 7996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // be compared. 8096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 2.0 * comparePackages(oldPkg, (PackageAPI)(newAPI.packages_.get(idx))); 8196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 8296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 8396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 8496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find packages which were added or changed in the new API 8596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project iter = newAPI.packages_.iterator(); 8696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 8796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project PackageAPI newPkg = (PackageAPI)(iter.next()); 8896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(oldAPI.packages_, newPkg); 8996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 9096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // See comments above 9196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int existsOld = oldAPI.packages_.indexOf(newPkg); 9296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (existsOld != -1) { 9396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Don't mark a package as added or compare it 9496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // if it was already marked as changed 9596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 9696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 9796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Package " + newPkg.name_ + " was added"); 9896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff.packagesAdded.add(newPkg); 9996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 1.0; 10096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 10196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 10296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // It will already have been compared above. 10396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 10496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 10596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 10696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Now that the numbers of members removed and added are known 10796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // we can deduce more information about changes. 10896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MergeChanges.mergeRemoveAdd(apiDiff); 10996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 11096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// The percent change statistic reported for all elements in each API is 11196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// defined recursively as follows: 11296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// 11396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// %age change = 100 * (added + removed + 2*changed) 11496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// ----------------------------------- 11596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// sum of public elements in BOTH APIs 11696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// 11796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// The definition ensures that if all classes are removed and all new classes 11896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// added, the change will be 100%. 11996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// Evaluation of the visibility of elements has already been done when the 12096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// XML was written out. 12196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// Note that this doesn't count changes in the modifiers of classes and 12296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// packages. Other changes in members are counted. 12396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Long denom = new Long(oldAPI.packages_.size() + newAPI.packages_.size()); 12496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // This should never be zero because an API always has packages? 12596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (denom.intValue() == 0) { 12696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Error: no packages found in the APIs."); 12796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return; 12896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 12996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 13096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Top level changes: " + differs + "/" + denom.intValue()); 13196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = (100.0 * differs)/denom.doubleValue(); 13296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 13396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Some differences such as documentation changes are not tracked in 13496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // the difference statistic, so a value of 0.0 does not mean that there 13596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // were no differences between the APIs. 13696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff.pdiff = differs; 13796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Double percentage = new Double(differs); 13896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int approxPercentage = percentage.intValue(); 13996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (approxPercentage == 0) 14096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Approximately " + percentage + "% difference between the APIs"); 14196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 14296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Approximately " + approxPercentage + "% difference between the APIs"); 14396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 14496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Diff.closeDiffFile(); 14596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 14696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 14796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 14896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare two packages. 14996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 15096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public double comparePackages(PackageAPI oldPkg, PackageAPI newPkg) { 15196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 15296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Comparing old package " + oldPkg.name_ + 15396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project " and new package " + newPkg.name_); 15496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff = new PackageDiff(oldPkg.name_); 15596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project double differs = 0.0; 15696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 15796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(oldPkg.classes_); 15896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(newPkg.classes_); 15996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 16096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find classes which were removed in the new package 16196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = oldPkg.classes_.iterator(); 16296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 16396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ClassAPI oldClass = (ClassAPI)(iter.next()); 16496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // This search is looking for an *exact* match. This is true in 16596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // all the *API classes. 16696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(newPkg.classes_, oldClass); 16796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 16896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // If there an instance of a class with the same name 16996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // in both the old and new package, then treat it as changed, 17096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // rather than removed and added. There will never be more than 17196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // one instance of a class with the same name in a package. 17296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int existsNew = newPkg.classes_.indexOf(oldClass); 17396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (existsNew != -1) { 17496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Class by the same name exists in both packages 17596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // but there has been some or other change. 17696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 2.0 * compareClasses(oldClass, (ClassAPI)(newPkg.classes_.get(existsNew)), pkgDiff); 17796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 17896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 17996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Class " + oldClass.name_ + " was removed"); 18096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff.classesRemoved.add(oldClass); 18196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 1.0; 18296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 18396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 18496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // The class exists unchanged in name or modifiers, but may 18596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // differ in members, so it still needs to be compared. 18696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 2.0 * compareClasses(oldClass, (ClassAPI)(newPkg.classes_.get(idx)), pkgDiff); 18796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 18896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 18996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 19096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find classes which were added or changed in the new package 19196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project iter = newPkg.classes_.iterator(); 19296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 19396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ClassAPI newClass = (ClassAPI)(iter.next()); 19496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(oldPkg.classes_, newClass); 19596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 19696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // See comments above 19796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int existsOld = oldPkg.classes_.indexOf(newClass); 19896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (existsOld != -1) { 19996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Don't mark a class as added or compare it 20096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // if it was already marked as changed 20196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 20296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 20396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Class " + newClass.name_ + " was added"); 20496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff.classesAdded.add(newClass); 20596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs += 1.0; 20696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 20796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 20896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // It will already have been compared above. 20996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 21096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 21196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 21296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Check if the only change was in documentation. Bug 472521. 21396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differsFlag = false; 21496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (docChanged(oldPkg.doc_, newPkg.doc_)) { 21596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link = "<a href=\"pkg_" + oldPkg.name_ + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">"; 21696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String id = oldPkg.name_ + "!package"; 21796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String title = link + "Package <b>" + oldPkg.name_ + "</b></a>"; 21896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, null, oldPkg.doc_, newPkg.doc_, id, title); 21996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 22096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 22196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 22296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only add to the parent Diff object if some difference has been found 22396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (differs != 0.0 || differsFlag) 22496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project apiDiff.packagesChanged.add(pkgDiff); 22596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 22696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Long denom = new Long(oldPkg.classes_.size() + newPkg.classes_.size()); 22796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // This should never be zero because a package always has classes? 22896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (denom.intValue() == 0) { 22996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Warning: no classes found in the package " + oldPkg.name_); 23096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 0.0; 23196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 23296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 23396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Package " + pkgDiff.name_ + " had a difference of " + differs + "/" + denom.intValue()); 23496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff.pdiff = 100.0 * differs/denom.doubleValue(); 23596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return differs/denom.doubleValue(); 23696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // comparePackages() 23796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 23896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 23996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare two classes. 24096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 24196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Need to compare constructors, methods and fields. 24296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 24396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public double compareClasses(ClassAPI oldClass, ClassAPI newClass, PackageDiff pkgDiff) { 24496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 24596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Comparing old class " + oldClass.name_ + 24696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project " and new class " + newClass.name_); 24796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differsFlag = false; 24896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project double differs = 0.0; 24996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ClassDiff classDiff = new ClassDiff(oldClass.name_); 25096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.isInterface_ = newClass.isInterface_; // Used in the report 25196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 25296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in modifiers - class or interface 25396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldClass.isInterface_ != newClass.isInterface_) { 25496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.modifiersChange_ = "Changed from "; 25596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldClass.isInterface_) 25696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.modifiersChange_ += "an interface to a class."; 25796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 25896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.modifiersChange_ += "a class to an interface."; 25996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 26096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 26196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in inheritance 26296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String inheritanceChange = ClassDiff.diff(oldClass, newClass); 26396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (inheritanceChange != null) { 26496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.inheritanceChange_ = inheritanceChange; 26596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 26696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 26796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Abstract or not 26896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldClass.isAbstract_ != newClass.isAbstract_) { 26996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = ""; 27096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldClass.isAbstract_) 27196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from abstract to non-abstract."; 27296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 27396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from non-abstract to abstract."; 27496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.addModifiersChange(changeText); 27596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 27696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 27796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in documentation 27896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (docChanged(oldClass.doc_, newClass.doc_)) { 27996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String fqName = pkgDiff.name_ + "." + classDiff.name_; 28096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">"; 28196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String id = pkgDiff.name_ + "." + classDiff.name_ + "!class"; 28296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String title = link + "Class <b>" + classDiff.name_ + "</b></a>"; 28396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, 28496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.name_, oldClass.doc_, newClass.doc_, id, title); 28596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 28696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 28796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // All other modifiers 28896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String modifiersChange = oldClass.modifiers_.diff(newClass.modifiers_); 28996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (modifiersChange != null) { 29096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 29196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) { 29296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("JDiff: warning: change from deprecated to undeprecated for class " + pkgDiff.name_ + "." + newClass.name_); 29396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 29496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 29596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 29696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.addModifiersChange(modifiersChange); 29796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 29896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in members 29996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differsCtors = 30096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project compareAllCtors(oldClass, newClass, classDiff); 30196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differsMethods = 30296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project compareAllMethods(oldClass, newClass, classDiff); 30396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differsFields = 30496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project compareAllFields(oldClass, newClass, classDiff); 30596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (differsCtors || differsMethods || differsFields) 30696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differsFlag = true; 30796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 30896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) { 30996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Ctors differ? " + differsCtors + 31096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ", Methods differ? " + differsMethods + 31196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ", Fields differ? " + differsFields); 31296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 31396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 31496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only add to the parent if some difference has been found 31596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (differsFlag) 31696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff.classesChanged.add(classDiff); 31796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 31896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Get the numbers of affected elements from the classDiff object 31996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = 32096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.ctorsRemoved.size() + classDiff.ctorsAdded.size() + 32196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.ctorsChanged.size() + 32296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.methodsRemoved.size() + classDiff.methodsAdded.size() + 32396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.methodsChanged.size() + 32496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.fieldsRemoved.size() + classDiff.fieldsAdded.size() + 32596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.fieldsChanged.size(); 32696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Long denom = new Long( 32796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldClass.ctors_.size() + 32896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project numLocalMethods(oldClass.methods_) + 32996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project numLocalFields(oldClass.fields_) + 33096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newClass.ctors_.size() + 33196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project numLocalMethods(newClass.methods_) + 33296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project numLocalFields(newClass.fields_)); 33396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (denom.intValue() == 0) { 33496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // This is probably a placeholder interface, but documentation 33596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // or modifiers etc may have changed 33696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (differsFlag) { 33796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.pdiff = 0.0; // 100.0 is too much 33896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 1.0; 33996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 34096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 0.0; 34196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 34296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 34396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Handle the case where the only change is in documentation or 34496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // the modifiers 34596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (differsFlag && differs == 0.0) { 34696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = 1.0; 34796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 34896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 34996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Class " + classDiff.name_ + " had a difference of " + differs + "/" + denom.intValue()); 35096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.pdiff = 100.0 * differs/denom.doubleValue(); 35196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return differs/denom.doubleValue(); 35296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // compareClasses() 35396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 35496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 35596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare all the constructors in two classes. 35696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 35796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * The compareTo method in the ConstructorAPI class acts only upon the type. 35896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 35996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public boolean compareAllCtors(ClassAPI oldClass, ClassAPI newClass, 36096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ClassDiff classDiff) { 36196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 36296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Comparing constructors: #old " + 36396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldClass.ctors_.size() + ", #new " + newClass.ctors_.size()); 36496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differs = false; 36596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean singleCtor = false; // Set if there is only one ctor 36696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 36796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(oldClass.ctors_); 36896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(newClass.ctors_); 36996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 37096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find ctors which were removed in the new class 37196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = oldClass.ctors_.iterator(); 37296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 37396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ConstructorAPI oldCtor = (ConstructorAPI)(iter.next()); 37496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(newClass.ctors_, oldCtor); 37596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 37696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int oldSize = oldClass.ctors_.size(); 37796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int newSize = newClass.ctors_.size(); 37896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldSize == 1 && oldSize == newSize) { 37996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // If there is one constructor in the oldClass and one 38096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // constructor in the new class, then mark it as changed 38196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MemberDiff memberDiff = new MemberDiff(oldClass.name_); 3820860aaa8b3cd01b42407009ffe4e0697ef0c1356C. Sean Young memberDiff.oldType_ = oldCtor.getSignature(); 38396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.oldExceptions_ = oldCtor.exceptions_; 38496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ConstructorAPI newCtor = (ConstructorAPI)(newClass.ctors_.get(0)); 3850860aaa8b3cd01b42407009ffe4e0697ef0c1356C. Sean Young memberDiff.newType_ = newCtor.getSignature(); 38696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.newExceptions_ = newCtor.exceptions_; 38796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in documentation 38896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (docChanged(oldCtor.doc_, newCtor.doc_)) { 38996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String type = memberDiff.newType_; 39096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (type.compareTo("void") == 0) 39196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project type = ""; 39296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String fqName = pkgDiff.name_ + "." + classDiff.name_; 39396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link1 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">"; 39496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link2 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "#" + fqName + ".ctor_changed(" + type + ")\" class=\"hiddenlink\">"; 39596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String id = pkgDiff.name_ + "." + classDiff.name_ + ".ctor(" + HTMLReportGenerator.simpleName(type) + ")"; 39696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String title = link1 + "Class <b>" + classDiff.name_ + 39796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project "</b></a>, " + link2 + "constructor <b>" + classDiff.name_ + "(" + HTMLReportGenerator.simpleName(type) + ")</b></a>"; 39896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.documentationChange_ = Diff.saveDocDiffs( 39996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgDiff.name_, classDiff.name_, oldCtor.doc_, newCtor.doc_, id, title); 40096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 40196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String modifiersChange = oldCtor.modifiers_.diff(newCtor.modifiers_); 40296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (modifiersChange != null && modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) { 40396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("JDiff: warning: change from deprecated to undeprecated for a constructor in class" + newClass.name_); 40496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 40596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange(modifiersChange); 40696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 40796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" The single constructor was changed"); 40896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.ctorsChanged.add(memberDiff); 40996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project singleCtor = true; 41096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 41196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 41296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Constructor " + oldClass.name_ + " was removed"); 41396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.ctorsRemoved.add(oldCtor); 41496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 41596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 41696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 41796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 41896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 41996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find ctors which were added in the new class 42096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project iter = newClass.ctors_.iterator(); 42196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 42296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ConstructorAPI newCtor = (ConstructorAPI)(iter.next()); 42396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(oldClass.ctors_, newCtor); 42496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 42596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (!singleCtor) { 42696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 42796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Constructor " + oldClass.name_ + " was added"); 42896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.ctorsAdded.add(newCtor); 42996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 43096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 43196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 43296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 43396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 43496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return differs; 43596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // compareAllCtors() 43696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 43796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 43896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare all the methods in two classes. 43996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 44096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * We have to deal with the cases where: 44196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * - there is only one method with a given name, but its signature changes 44296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * - there is more than one method with the same name, and some of them 44396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * may have signature changes 44496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * The simplest way to deal with this is to make the MethodAPI comparator 44596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * check the params and return type, as well as the name. This means that 44696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * changing a parameter's type would cause the method to be seen as 44796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * removed and added. To avoid this for the simple case, check for before 44896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * recording a method as removed or added. 44996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 45096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public boolean compareAllMethods(ClassAPI oldClass, ClassAPI newClass, ClassDiff classDiff) { 45196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 45296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Comparing methods: #old " + 45396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldClass.methods_.size() + ", #new " + 45496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newClass.methods_.size()); 45596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differs = false; 45696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 45796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(oldClass.methods_); 45896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(newClass.methods_); 45996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 46096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find methods which were removed in the new class 46196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = oldClass.methods_.iterator(); 46296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 46396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI oldMethod = (MethodAPI)(iter.next()); 46496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = -1; 46596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI[] methodArr = new MethodAPI[newClass.methods_.size()]; 46696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodArr = (MethodAPI[])newClass.methods_.toArray(methodArr); 46796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project for (int methodIdx = 0; methodIdx < methodArr.length; methodIdx++) { 46896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI newMethod = methodArr[methodIdx]; 46996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.compareTo(newMethod) == 0) { 47096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project idx = methodIdx; 47196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project break; 47296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 47396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 47496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// NOTE: there was a problem with the binarySearch for 47596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// java.lang.Byte.toString(byte b) returning -16 when the compareTo method 47696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// returned 0 on entry 13. Changed to use arrays instead, so maybe it was 47796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// an issue with methods having another List of params used indirectly by 47896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// compareTo(), unlike constructors and fields? 47996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// int idx = Collections.binarySearch(newClass.methods_, oldMethod); 48096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 48196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // If there is only one instance of a method with this name 48296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // in both the old and new class, then treat it as changed, 48396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // rather than removed and added. 48496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find how many instances of this method name there are in 48596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // the old and new class. The equals comparator is just on 48696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // the method name. 48796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int startOld = oldClass.methods_.indexOf(oldMethod); 48896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int endOld = oldClass.methods_.lastIndexOf(oldMethod); 48996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int startNew = newClass.methods_.indexOf(oldMethod); 49096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int endNew = newClass.methods_.lastIndexOf(oldMethod); 49196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 49296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (startOld != -1 && startOld == endOld && 49396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project startNew != -1 && startNew == endNew) { 49496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI newMethod = (MethodAPI)(newClass.methods_.get(startNew)); 49596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only one method with that name exists in both packages, 49696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // so it is valid to compare the two methods. We know it 49796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // has changed, because the binarySearch did not find it. 49896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.inheritedFrom_ == null || 49996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newMethod.inheritedFrom_ == null) { 50096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // We also know that at least one of the methods is 50196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // locally defined. 50296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project compareMethods(oldMethod, newMethod, classDiff); 50396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 50496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 50596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else if (oldMethod.inheritedFrom_ == null) { 50696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only concerned with locally defined methods 50796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 50896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Method " + oldMethod.name_ + 50996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project "(" + oldMethod.getSignature() + 51096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ") was removed"); 51196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.methodsRemoved.add(oldMethod); 51296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 51396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 51496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 51596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 51696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 51796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find methods which were added in the new class 51896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project iter = newClass.methods_.iterator(); 51996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 52096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI newMethod = (MethodAPI)(iter.next()); 52196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only concerned with locally defined methods 52296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (newMethod.inheritedFrom_ != null) 52396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project continue; 52496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = -1; 52596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI[] methodArr = new MethodAPI[oldClass.methods_.size()]; 52696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodArr = (MethodAPI[])oldClass.methods_.toArray(methodArr); 52796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project for (int methodIdx = 0; methodIdx < methodArr.length; methodIdx++) { 52896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI oldMethod = methodArr[methodIdx]; 52996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (newMethod.compareTo(oldMethod) == 0) { 53096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project idx = methodIdx; 53196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project break; 53296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 53396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 53496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// See note above about searching an array instead of binarySearch 53596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project// int idx = Collections.binarySearch(oldClass.methods_, newMethod); 53696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 53796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // See comments above 53896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int startOld = oldClass.methods_.indexOf(newMethod); 53996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int endOld = oldClass.methods_.lastIndexOf(newMethod); 54096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int startNew = newClass.methods_.indexOf(newMethod); 54196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int endNew = newClass.methods_.lastIndexOf(newMethod); 54296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 54396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (startOld != -1 && startOld == endOld && 54496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project startNew != -1 && startNew == endNew) { 54596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Don't mark a method as added if it was marked as changed 54696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // The comparison will have been done just above here. 54796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 54896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 54996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Method " + newMethod.name_ + 55096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project "(" + newMethod.getSignature() + ") was added"); 55196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.methodsAdded.add(newMethod); 55296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 55396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 55496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 55596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 55696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 55796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return differs; 55896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // compareAllMethods() 55996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 56096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 56196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare two methods which have the same name. 56296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 56396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public boolean compareMethods(MethodAPI oldMethod, MethodAPI newMethod, ClassDiff classDiff) { 56496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MemberDiff methodDiff = new MemberDiff(oldMethod.name_); 56596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differs = false; 56696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Check changes in return type 56796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.oldType_ = oldMethod.returnType_; 56896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.newType_ = newMethod.returnType_; 56996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.returnType_.compareTo(newMethod.returnType_) != 0) { 57096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 57196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 57296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Check changes in signature 57396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String oldSig = oldMethod.getSignature(); 57496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String newSig = newMethod.getSignature(); 57596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.oldSignature_ = oldSig; 57696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.newSignature_ = newSig; 57796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldSig.compareTo(newSig) != 0) { 57896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 57996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 58096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Changes in inheritance 58196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int inh = changedInheritance(oldMethod.inheritedFrom_, newMethod.inheritedFrom_); 58296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (inh != 0) 58396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 58496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (inh == 1) { 58596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange("Method was locally defined, but is now inherited from " + linkToClass(newMethod, true) + "."); 58696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.inheritedFrom_ = newMethod.inheritedFrom_; 58796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else if (inh == 2) { 58896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange("Method was inherited from " + linkToClass(oldMethod, false) + ", but is now defined locally."); 58996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else if (inh == 3) { 59096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange("Method was inherited from " + 59196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project linkToClass(oldMethod, false) + ", and is now inherited from " + linkToClass(newMethod, true) + "."); 59296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.inheritedFrom_ = newMethod.inheritedFrom_; 59396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 59496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Abstract or not 59596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.isAbstract_ != newMethod.isAbstract_) { 59696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = ""; 59796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.isAbstract_) 59896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from abstract to non-abstract."; 59996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 60096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from non-abstract to abstract."; 60196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange(changeText); 60296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 60396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 60496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Native or not 60596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (Diff.showAllChanges && 60696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldMethod.isNative_ != newMethod.isNative_) { 60796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = ""; 60896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.isNative_) 60996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from native to non-native."; 61096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 61196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from non-native to native."; 61296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange(changeText); 61396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 61496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 61596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Synchronized or not 61696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (Diff.showAllChanges && 61796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldMethod.isSynchronized_ != newMethod.isSynchronized_) { 61896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = ""; 61996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.isSynchronized_) 62096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from synchronized to non-synchronized."; 62196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 62296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from non-synchronized to synchronized."; 62396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange(changeText); 62496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 62596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 62696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 62796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Check changes in exceptions thrown 62896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.oldExceptions_ = oldMethod.exceptions_; 62996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.newExceptions_ = newMethod.exceptions_; 63096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldMethod.exceptions_.compareTo(newMethod.exceptions_) != 0) { 63196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 63296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 63396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 63496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in documentation 63596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (docChanged(oldMethod.doc_, newMethod.doc_)) { 63696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String sig = methodDiff.newSignature_; 63796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (sig.compareTo("void") == 0) 63896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project sig = ""; 63996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String fqName = pkgDiff.name_ + "." + classDiff.name_; 64096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link1 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">"; 64196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link2 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "#" + fqName + "." + newMethod.name_ + "_changed(" + sig + ")\" class=\"hiddenlink\">"; 64296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String id = pkgDiff.name_ + "." + classDiff.name_ + ".dmethod." + newMethod.name_ + "(" + HTMLReportGenerator.simpleName(sig) + ")"; 64396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String title = link1 + "Class <b>" + classDiff.name_ + "</b></a>, " + 64496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project link2 + HTMLReportGenerator.simpleName(methodDiff.newType_) + " <b>" + newMethod.name_ + "(" + HTMLReportGenerator.simpleName(sig) + ")</b></a>"; 64596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, classDiff.name_, oldMethod.doc_, newMethod.doc_, id, title); 64696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 64796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 64896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 64996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // All other modifiers 65096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String modifiersChange = oldMethod.modifiers_.diff(newMethod.modifiers_); 65196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (modifiersChange != null) { 65296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 65396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) { 65496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("JDiff: warning: change from deprecated to undeprecated for method " + classDiff.name_ + "." + newMethod.name_); 65596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 65696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 65796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 65896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project methodDiff.addModifiersChange(modifiersChange); 65996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 66096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only add to the parent if some difference has been found 66196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (differs) { 66296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) { 66396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Method " + newMethod.name_ + 66496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project " was changed: old: " + 66596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldMethod.returnType_ + "(" + oldSig + "), new: " + 66696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newMethod.returnType_ + "(" + newSig + ")"); 66796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (methodDiff.modifiersChange_ != null) 66896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Modifier change: " + methodDiff.modifiersChange_); 66996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 67096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.methodsChanged.add(methodDiff); 67196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 67296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 67396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return differs; 67496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // compareMethods() 67596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 67696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 67796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Compare all the fields in two classes. 67896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 67996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public boolean compareAllFields(ClassAPI oldClass, ClassAPI newClass, 68096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ClassDiff classDiff) { 68196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 68296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Comparing fields: #old " + 68396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldClass.fields_.size() + ", #new " 68496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project + newClass.fields_.size()); 68596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project boolean differs = false; 68696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 68796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(oldClass.fields_); 68896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Collections.sort(newClass.fields_); 68996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 69096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find fields which were removed in the new class 69196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = oldClass.fields_.iterator(); 69296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 69396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project FieldAPI oldField = (FieldAPI)(iter.next()); 69496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(newClass.fields_, oldField); 69596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 69696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // If there an instance of a field with the same name 69796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // in both the old and new class, then treat it as changed, 69896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // rather than removed and added. There will never be more than 69996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // one instance of a field with the same name in a class. 70096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int existsNew = newClass.fields_.indexOf(oldField); 70196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (existsNew != -1) { 70296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project FieldAPI newField = (FieldAPI)(newClass.fields_.get(existsNew)); 70396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldField.inheritedFrom_ == null || 70496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newField.inheritedFrom_ == null) { 70596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // We also know that one of the fields is locally defined. 70696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MemberDiff memberDiff = new MemberDiff(oldField.name_); 70796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.oldType_ = oldField.type_; 70896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.newType_ = newField.type_; 70996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Changes in inheritance 71096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int inh = changedInheritance(oldField.inheritedFrom_, newField.inheritedFrom_); 71196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (inh != 0) 71296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 71396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (inh == 1) { 71496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange("Field was locally defined, but is now inherited from " + linkToClass(newField, true) + "."); 71596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.inheritedFrom_ = newField.inheritedFrom_; 71696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else if (inh == 2) { 71796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange("Field was inherited from " + linkToClass(oldField, false) + ", but is now defined locally."); 71896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else if (inh == 3) { 71996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange("Field was inherited from " + linkToClass(oldField, false) + ", and is now inherited from " + linkToClass(newField, true) + "."); 72096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.inheritedFrom_ = newField.inheritedFrom_; 72196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 72296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Transient or not 72396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldField.isTransient_ != newField.isTransient_) { 72496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = ""; 72596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldField.isTransient_) 72696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from transient to non-transient."; 72796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 72896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from non-transient to transient."; 72996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange(changeText); 73096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 73196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 73296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Volatile or not 73396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldField.isVolatile_ != newField.isVolatile_) { 73496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = ""; 73596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldField.isVolatile_) 73696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from volatile to non-volatile."; 73796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 73896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project changeText += "Changed from non-volatile to volatile."; 73996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange(changeText); 74096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 74196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 74296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Change in value of the field 74396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldField.value_ != null && 74496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project newField.value_ != null && 74596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project oldField.value_.compareTo(newField.value_) != 0) { 74696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String changeText = "Changed in value from " + oldField.value_ 74796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project + " to " + newField.value_ +"."; 74896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange(changeText); 74996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 75096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 75196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Track changes in documentation 75296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (docChanged(oldField.doc_, newField.doc_)) { 75396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String fqName = pkgDiff.name_ + "." + classDiff.name_; 75496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link1 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "\" class=\"hiddenlink\">"; 75596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String link2 = "<a href=\"" + fqName + HTMLReportGenerator.reportFileExt + "#" + fqName + "." + newField.name_ + "\" class=\"hiddenlink\">"; 75696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String id = pkgDiff.name_ + "." + classDiff.name_ + ".field." + newField.name_; 75796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String title = link1 + "Class <b>" + classDiff.name_ + "</b></a>, " + 75896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project link2 + HTMLReportGenerator.simpleName(memberDiff.newType_) + " <b>" + newField.name_ + "</b></a>"; 75996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.documentationChange_ = Diff.saveDocDiffs(pkgDiff.name_, classDiff.name_, oldField.doc_, newField.doc_, id, title); 76096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 76196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 76296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 76396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Other differences 76496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String modifiersChange = oldField.modifiers_.diff(newField.modifiers_); 76596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project memberDiff.addModifiersChange(modifiersChange); 76696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (modifiersChange != null && modifiersChange.indexOf("Change from deprecated to undeprecated") != -1) { 76796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("JDiff: warning: change from deprecated to undeprecated for class " + newClass.name_ + ", field " + newField.name_); 76896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 76996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 77096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Field " + newField.name_ + " was changed"); 77196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.fieldsChanged.add(memberDiff); 77296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 77396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 77496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else if (oldField.inheritedFrom_ == null) { 77596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 77696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Field " + oldField.name_ + " was removed"); 77796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.fieldsRemoved.add(oldField); 77896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 77996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 78096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 78196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 78296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 78396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Find fields which were added in the new class 78496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project iter = newClass.fields_.iterator(); 78596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 78696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project FieldAPI newField = (FieldAPI)(iter.next()); 78796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Only concerned with locally defined fields 78896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (newField.inheritedFrom_ != null) 78996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project continue; 79096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int idx = Collections.binarySearch(oldClass.fields_, newField); 79196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (idx < 0) { 79296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // See comments above 79396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int existsOld = oldClass.fields_.indexOf(newField); 79496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (existsOld != -1) { 79596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project // Don't mark a field as added if it was marked as changed 79696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } else { 79796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (trace) 79896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println(" Field " + newField.name_ + " was added"); 79996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project classDiff.fieldsAdded.add(newField); 80096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project differs = true; 80196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 80296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 80396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // while (iter.hasNext()) 80496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 80596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return differs; 80696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } // compareFields() 80796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 80896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 80996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Decide if two blocks of documentation changed. 81096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 81196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * @return true if both are non-null and differ, 81296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * or if one is null and the other is not. 81396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 81496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public static boolean docChanged(String oldDoc, String newDoc) { 81596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (!HTMLReportGenerator.reportDocChanges) 81696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return false; // Don't even count doc changes as changes 81796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldDoc == null && newDoc != null) 81896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return true; 81996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldDoc != null && newDoc == null) 82096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return true; 82196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldDoc != null && newDoc != null && oldDoc.compareTo(newDoc) != 0) 82296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return true; 82396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return false; 82496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 82596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 82696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 82796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Decide if two elements changed where they were defined. 82896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 82996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * @return 0 if both are null, or both are non-null and are the same. 83096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 1 if the oldInherit was null and newInherit is non-null. 83196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 2 if the oldInherit was non-null and newInherit is null. 83296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * 3 if the oldInherit was non-null and newInherit is non-null 83396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * and they differ. 83496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 83596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public static int changedInheritance(String oldInherit, String newInherit) { 83696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldInherit == null && newInherit == null) 83796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 0; 83896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldInherit == null && newInherit != null) 83996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 1; 84096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldInherit != null && newInherit == null) 84196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 2; 84296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (oldInherit.compareTo(newInherit) == 0) 84396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 0; 84496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 84596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return 3; 84696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 84796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 84896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 84996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Generate a link to the Javadoc page for the given method. 85096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 85196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public static String linkToClass(MethodAPI m, boolean useNew) { 85296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String sig = m.getSignature(); 85396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (sig.compareTo("void") == 0) 85496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project sig = ""; 85596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return linkToClass(m.inheritedFrom_, m.name_, sig, useNew); 85696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 85796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 85896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 85996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Generate a link to the Javadoc page for the given field. 86096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 86196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public static String linkToClass(FieldAPI m, boolean useNew) { 86296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return linkToClass(m.inheritedFrom_, m.name_, null, useNew); 86396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 86496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 86596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 86696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Given the name of the class, generate a link to a relevant page. 86796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * This was originally for inheritance changes, so the JDiff page could 86896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * be a class changes page, or a section in a removed or added classes 86996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * table. Since there was no easy way to tell which type the link 87096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * should be, it is now just a link to the relevant Javadoc page. 87196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 87296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public static String linkToClass(String className, String memberName, 87396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String memberType, boolean useNew) { 87496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (!useNew && HTMLReportGenerator.oldDocPrefix == null) { 87596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return "<tt>" + className + "</tt>"; // No link possible 87696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 87796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project API api = oldAPI_; 87896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String prefix = HTMLReportGenerator.oldDocPrefix; 87996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (useNew) { 88096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project api = newAPI_; 88196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project prefix = HTMLReportGenerator.newDocPrefix; 88296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 88396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project ClassAPI cls = (ClassAPI)api.classes_.get(className); 88496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (cls == null) { 88596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (useNew) 88696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Warning: class " + className + " not found in the new API when creating Javadoc link"); 88796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project else 88896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project System.out.println("Warning: class " + className + " not found in the old API when creating Javadoc link"); 88996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return "<tt>" + className + "</tt>"; 89096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 89196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int clsIdx = className.indexOf(cls.name_); 89296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (clsIdx != -1) { 89396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String pkgRef = className.substring(0, clsIdx); 89496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project pkgRef = pkgRef.replace('.', '/'); 89596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project String res = "<a href=\"" + prefix + pkgRef + cls.name_ + ".html#" + memberName; 89696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (memberType != null) 89796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project res += "(" + memberType + ")"; 89896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project res += "\" target=\"_top\">" + "<tt>" + cls.name_ + "</tt></a>"; 89996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return res; 90096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 90196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return "<tt>" + className + "</tt>"; 90296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 90396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 90496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 90596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Return the number of methods which are locally defined. 90696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 90796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public int numLocalMethods(List methods) { 90896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int res = 0; 90996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = methods.iterator(); 91096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 91196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project MethodAPI m = (MethodAPI)(iter.next()); 91296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (m.inheritedFrom_ == null) 91396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project res++; 91496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 91596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return res; 91696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 91796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 91896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** 91996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project * Return the number of fields which are locally defined. 92096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project */ 92196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project public int numLocalFields(List fields) { 92296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project int res = 0; 92396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project Iterator iter = fields.iterator(); 92496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project while (iter.hasNext()) { 92596b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project FieldAPI f = (FieldAPI)(iter.next()); 92696b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project if (f.inheritedFrom_ == null) 92796b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project res++; 92896b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 92996b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project return res; 93096b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project } 93196b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project 93296b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project /** Set to enable increased logging verbosity for debugging. */ 93396b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project private boolean trace = false; 93496b00fec6cd6068c1c5ae09de0358340c0ec499eThe Android Open Source Project} 935