Changeset 12872 in josm for trunk/tools/japicc/japi-compliance-checker.pl
- Timestamp:
- 2017-09-17T15:47:18+02:00 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/japicc/japi-compliance-checker.pl
r11682 r12872 1 1 #!/usr/bin/perl 2 2 ########################################################################### 3 # Java API Compliance Checker (JAPICC) 2. 13 # Java API Compliance Checker (JAPICC) 2.3 4 4 # A tool for checking backward compatibility of a Java library API 5 5 # … … 43 43 use Data::Dumper; 44 44 45 my $TOOL_VERSION = "2. 1";46 my $API_DUMP_VERSION = "2. 1";47 my $API_DUMP_VERSION_MIN = "2. 0";45 my $TOOL_VERSION = "2.3"; 46 my $API_DUMP_VERSION = "2.2"; 47 my $API_DUMP_VERSION_MIN = "2.2"; 48 48 49 49 # Internal modules … … 110 110 "skip-internal-types=s" => \$In::Opt{"SkipInternalTypes"}, 111 111 "dump|dump-api=s" => \$In::Opt{"DumpAPI"}, 112 "check-packages=s" => \$In::Opt{"CheckPackages"}, 112 113 "classes-list=s" => \$In::Opt{"ClassListPath"}, 113 114 "annotations-list=s" => \$In::Opt{"AnnotationsListPath"}, … … 291 292 292 293 -skip-internal-packages PATTERN 293 Do not check packages matched by the pattern.294 Do not check packages matched by the regular expression. 294 295 295 296 -skip-internal-types PATTERN 296 Do not check types (classes and interfaces) matched by the pattern. 297 Do not check types (classes and interfaces) matched by the regular 298 expression. It's matched against full qualified type names (e.g. 299 'org.xyz.Name<T>'). It has to match any part of type name. 297 300 298 301 -dump|-dump-api PATH 299 302 Dump library API to gzipped TXT format file. You can transfer it 300 303 anywhere and pass instead of the descriptor. Also it may be used 301 for debugging the tool. 302 304 for debugging the tool. PATH is the path to the Java archive or 305 XML descriptor of the library. 306 307 -check-packages PATTERN 308 Check packages matched by the regular expression. Other packages 309 will not be checked. 310 303 311 -classes-list PATH 304 312 This option allows to specify a file with a list … … 441 449 #Aliases 442 450 my (%MethodInfo, %TypeInfo, %TName_Tid) = (); 451 452 my %TName_Tid_Generic = (); 443 453 444 454 #Separate checked and unchecked exceptions … … 522 532 my %LibArchives; 523 533 my %Class_Methods; 534 my %Class_Methods_Generic; 524 535 my %Class_AbstractMethods; 525 536 my %Class_Fields; … … 530 541 my %CheckedMethods; 531 542 my %MethodUsed; 543 my %OldMethodSignature; 532 544 533 545 #Merging … … 537 549 my %CompatRules; 538 550 my %IncompleteRules; 551 my %UnknownRules; 539 552 540 553 #Report … … 623 636 { 624 637 next if(not $ClassName); 625 my $Type1 = getType($TName_Tid{1}{$ClassName}, 1); 638 my $Type1_Id = $TName_Tid{1}{$ClassName}; 639 my $Type1 = getType($Type1_Id, 1); 626 640 627 641 if($Type1->{"Type"}!~/class|interface/) { … … 634 648 } 635 649 636 if(not classFilter($Type1, 1, 0)) {650 if(not classFilter($Type1, 1, 1)) { 637 651 next; 638 652 } 639 653 640 my $Type2_Id = $TName_Tid{2}{$ClassName}; 641 if(not $Type2_Id) 654 my $GenericName = getGeneric($ClassName); 655 my $Type2_Id = undef; 656 657 if(defined $TName_Tid{2}{$ClassName}) { 658 $Type2_Id = $TName_Tid{2}{$ClassName}; 659 } 660 elsif(defined $TName_Tid_Generic{2}{$GenericName}) { 661 $Type2_Id = $TName_Tid_Generic{2}{$GenericName}; 662 } 663 664 if($Type2_Id) 665 { 666 my $TName1 = $Type1->{"Name"}; 667 my $TName2 = getTypeName($Type2_Id, 2); 668 669 my $Generic1 = (index($TName1, "<")!=-1); 670 my $Generic2 = (index($TName2, "<")!=-1); 671 672 if($Generic1 ne $Generic2) 673 { # removed generic parameters 674 foreach my $Method (keys(%{$Class_Methods{1}{$ClassName}})) 675 { 676 if(not methodFilter($Method, 1)) { 677 next; 678 } 679 680 $CheckedTypes{$ClassName} = 1; 681 $CheckedMethods{$Method} = 1; 682 683 if($Type1->{"Type"} eq "class") 684 { 685 if($Generic1) 686 { 687 %{$CompatProblems{$Method}{"Class_Became_Raw"}{"this"}} = ( 688 "Type_Name"=>$ClassName, 689 "New_Value"=>$TName2, 690 "Target"=>$ClassName); 691 } 692 else 693 { 694 %{$CompatProblems{$Method}{"Class_Became_Generic"}{"this"}} = ( 695 "Type_Name"=>$ClassName, 696 "New_Value"=>$TName2, 697 "Target"=>$ClassName); 698 } 699 } 700 else 701 { 702 if($Generic1) 703 { 704 %{$CompatProblems{$Method}{"Interface_Became_Raw"}{"this"}} = ( 705 "Type_Name"=>$ClassName, 706 "New_Value"=>$TName2, 707 "Target"=>$ClassName); 708 } 709 else 710 { 711 %{$CompatProblems{$Method}{"Interface_Became_Generic"}{"this"}} = ( 712 "Type_Name"=>$ClassName, 713 "New_Value"=>$TName2, 714 "Target"=>$ClassName); 715 } 716 } 717 } 718 } 719 } 720 else 642 721 { # classes and interfaces with public methods 643 722 foreach my $Method (keys(%{$Class_Methods{1}{$ClassName}})) … … 686 765 687 766 my $ClassName = $Class1->{"Name"}; 688 689 if(my $Class2_Id = $TName_Tid{2}{$ClassName}) 767 my $GenericName = getGeneric($ClassName); 768 my $Class2_Id = undef; 769 770 if(defined $TName_Tid{2}{$ClassName}) { 771 $Class2_Id = $TName_Tid{2}{$ClassName}; 772 } 773 elsif(defined $TName_Tid_Generic{2}{$GenericName}) { 774 $Class2_Id = $TName_Tid_Generic{2}{$GenericName}; 775 } 776 777 if($Class2_Id) 690 778 { # classes and interfaces with public static fields 691 779 if(not defined $Class_Methods{1}{$ClassName}) … … 869 957 return {} if(not $Type1{"Name"} or not $Type2{"Name"}); 870 958 return {} if(not $Type1{"Archive"} or not $Type2{"Archive"}); 871 return {} if($Type1{"Name"} ne $Type2{"Name"}); 872 873 if(not classFilter(\%Type1, 1, 0)) { 959 if($Type1{"Name"} ne $Type2{"Name"}) 960 { 961 if(getGeneric($Type1{"Name"}) ne getGeneric($Type2{"Name"})) 962 { # compare type declarations if became generic or raw 963 return {}; 964 } 965 } 966 967 if(not classFilter(\%Type1, 1, 1)) { 874 968 return {}; 875 969 } … … 925 1019 pushType($Type1_Id, $Type2_Id); 926 1020 927 foreach my $AddedMethod (keys(%{$AddedMethod_Abstract{$Type 1{"Name"}}}))1021 foreach my $AddedMethod (keys(%{$AddedMethod_Abstract{$Type2{"Name"}}})) 928 1022 { 929 1023 if($Type1{"Type"} eq "class") … … 1000 1094 my $SuperClassName2 = $SuperClass2->{"Name"}; 1001 1095 1096 # Java 6: java.lang.Object 1097 # Java 7: none 1098 if(not $SuperClassName1) { 1099 $SuperClassName1 = "java.lang.Object"; 1100 } 1101 1102 if(not $SuperClassName2) { 1103 $SuperClassName2 = "java.lang.Object"; 1104 } 1105 1002 1106 if($SuperClassName2 ne $SuperClassName1) 1003 1107 { 1004 if($SuperClassName1 eq "java.lang.Object" 1005 or not $SuperClassName1) 1006 { 1007 # Java 6: java.lang.Object 1008 # Java 7: none 1009 if($SuperClassName2 ne "java.lang.Object") 1108 if($SuperClassName1 eq "java.lang.Object") 1109 { 1110 if($SuperClass2->{"Abstract"} 1111 and $Type1{"Abstract"} and $Type2{"Abstract"} 1112 and keys(%{$Class_AbstractMethods{2}{$SuperClassName2}})) 1010 1113 { 1011 if($SuperClass2->{"Abstract"} 1012 and $Type1{"Abstract"} and $Type2{"Abstract"} 1013 and keys(%{$Class_AbstractMethods{2}{$SuperClassName2}})) 1114 if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"})) 1014 1115 { 1015 if(my ($Invoked, $InvokedBy) = getInvoked($Type1{"Name"})) 1016 { 1017 %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"}{""}} = ( 1018 "Type_Name"=>$Type1{"Name"}, 1019 "Target"=>$SuperClassName2, 1020 "Invoked"=>$Invoked, 1021 "Invoked_By"=>$InvokedBy); 1022 } 1023 else 1024 { 1025 %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class"}{""}} = ( 1026 "Type_Name"=>$Type1{"Name"}, 1027 "Target"=>$SuperClassName2); 1028 } 1116 %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class_Invoked_By_Others"}{""}} = ( 1117 "Type_Name"=>$Type1{"Name"}, 1118 "Target"=>$SuperClassName2, 1119 "Invoked"=>$Invoked, 1120 "Invoked_By"=>$InvokedBy); 1029 1121 } 1030 1122 else 1031 1123 { 1032 %{$SubProblems{"A dded_Super_Class"}{""}} = (1124 %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class"}{""}} = ( 1033 1125 "Type_Name"=>$Type1{"Name"}, 1034 1126 "Target"=>$SuperClassName2); 1035 1127 } 1036 1128 } 1037 } 1038 elsif($SuperClassName2 eq "java.lang.Object" 1039 or not $SuperClassName2) 1040 { 1041 # Java 6: java.lang.Object 1042 # Java 7: none 1043 if($SuperClassName1 ne "java.lang.Object") 1129 else 1044 1130 { 1045 %{$SubProblems{" Removed_Super_Class"}{""}} = (1131 %{$SubProblems{"Added_Super_Class"}{""}} = ( 1046 1132 "Type_Name"=>$Type1{"Name"}, 1047 "Target"=>$SuperClassName1); 1048 } 1133 "Target"=>$SuperClassName2); 1134 } 1135 } 1136 elsif($SuperClassName2 eq "java.lang.Object") 1137 { 1138 %{$SubProblems{"Removed_Super_Class"}{""}} = ( 1139 "Type_Name"=>$Type1{"Name"}, 1140 "Target"=>$SuperClassName1); 1049 1141 } 1050 1142 else … … 1337 1429 } 1338 1430 1339 my %Sub_SubChanges = detectTypeChange( $FieldType1_Id, $FieldType2_Id, "Field");1431 my %Sub_SubChanges = detectTypeChange(\%Type1, \%Type2, $FieldType1_Id, $FieldType2_Id, "Field"); 1340 1432 foreach my $Sub_SubProblemType (keys(%Sub_SubChanges)) 1341 1433 { … … 1460 1552 { 1461 1553 my ($Method, $MethodVersion, $ClassName, $ClassVersion) = @_; 1462 my $ClassId = $TName_Tid{$ClassVersion}{$ClassName}; 1554 1555 my $GenericName = getGeneric($ClassName); 1556 my $ClassId = undef; 1557 1558 if(defined $TName_Tid{$ClassVersion}{$ClassName}) { 1559 $ClassId = $TName_Tid{$ClassVersion}{$ClassName}; 1560 } 1561 elsif(defined $TName_Tid_Generic{$ClassVersion}{$GenericName}) { 1562 $ClassId = $TName_Tid_Generic{$ClassVersion}{$GenericName}; 1563 } 1463 1564 1464 1565 if($ClassId) … … 1517 1618 { 1518 1619 my ($Method, $ClassName, $ClassVersion) = @_; 1620 1519 1621 my $TargetSuffix = getMSuffix($Method); 1520 1622 my $TargetShortName = getMShort($Method); 1521 1522 if(not defined $Class_Methods{$ClassVersion}{$ClassName}) { 1623 my $GenericName = getGeneric($ClassName); 1624 1625 my @Candidates = (); 1626 1627 if(defined $Class_Methods{$ClassVersion}{$ClassName}) { 1628 @Candidates = keys(%{$Class_Methods{$ClassVersion}{$ClassName}}); 1629 } 1630 elsif(defined $Class_Methods_Generic{$ClassVersion}{$GenericName}) { 1631 @Candidates = keys(%{$Class_Methods_Generic{$ClassVersion}{$GenericName}}); 1632 } 1633 else { 1523 1634 return undef; 1524 1635 } 1525 1636 1526 foreach my $Candidate (sort keys(%{$Class_Methods{$ClassVersion}{$ClassName}}))1637 foreach my $Candidate (sort @Candidates) 1527 1638 { # search for method with the same parameters suffix 1528 1639 next if($MethodInfo{$ClassVersion}{$Candidate}{"Constructor"}); 1640 1529 1641 if($TargetSuffix eq getMSuffix($Candidate)) 1530 1642 { … … 1538 1650 } 1539 1651 1652 sub getBaseSignature($) 1653 { 1654 my $Method = $_[0]; 1655 $Method=~s/\)(.+)\Z/\)/g; 1656 return $Method; 1657 } 1658 1540 1659 sub prepareData($) 1541 1660 { … … 1558 1677 $TName_Tid{$LVer}{$TName} = $TypeId; 1559 1678 1679 if(defined $TypeAttr->{"Archive"}) 1680 { # declaration 1681 $TName_Tid_Generic{$LVer}{getGeneric($TName)} = $TypeId; 1682 } 1683 1560 1684 if(not $TypeAttr->{"Dep"}) 1561 1685 { … … 1590 1714 my $CName = getTypeName($ClassId, $LVer); 1591 1715 $Class_Methods{$LVer}{$CName}{$Method} = 1; 1716 $Class_Methods_Generic{$LVer}{getGeneric($CName)}{$Method} = 1; 1717 1592 1718 if($MAttr->{"Abstract"}) { 1593 1719 $Class_AbstractMethods{$LVer}{$CName}{$Method} = 1; … … 1603 1729 registerUsage($MAttr->{"Return"}, $LVer); 1604 1730 } 1731 } 1732 1733 if($LVer==1 and not $MAttr->{"Constructor"} 1734 and my $BaseSign = getBaseSignature($Method)) { 1735 $OldMethodSignature{$BaseSign} = $Method; 1605 1736 } 1606 1737 } … … 1857 1988 # checking type declaration changes 1858 1989 my $SubProblems = mergeTypes($ParamType1_Id, $ParamType2_Id); 1990 1991 my $Type1 = getType($ParamType1_Id, 1); 1992 my $Type2 = getType($ParamType2_Id, 2); 1993 1994 if($Type1->{"Name"} ne $Type2->{"Name"}) 1995 { 1996 if(index($Type1->{"Name"}, "...")!=-1 and index($Type2->{"Name"}, "[]")!=-1) 1997 { 1998 %{$CompatProblems{$Method}{"Variable_Arity_To_Array"}{$Parameter_Name}} = ( 1999 "Type_Name"=>getTypeName($MethodInfo{1}{$Method}{"Class"}, 1), 2000 "Param_Name"=>$Parameter_Name, 2001 "Old_Value"=>$Type1->{"Name"}, 2002 "New_Value"=>$Type2->{"Name"}); 2003 } 2004 elsif(index($Type1->{"Name"}, "[]")!=-1 and index($Type2->{"Name"}, "...")!=-1) 2005 { 2006 %{$CompatProblems{$Method}{"Array_To_Variable_Arity"}{$Parameter_Name}} = ( 2007 "Type_Name"=>getTypeName($MethodInfo{1}{$Method}{"Class"}, 1), 2008 "Param_Name"=>$Parameter_Name, 2009 "Old_Value"=>$Type1->{"Name"}, 2010 "New_Value"=>$Type2->{"Name"}); 2011 } 2012 } 2013 1859 2014 foreach my $SubProblemType (keys(%{$SubProblems})) 1860 2015 { … … 1867 2022 } 1868 2023 1869 sub detectTypeChange($$$ )1870 { 1871 my ($ Type1_Id, $Type2_Id, $Prefix) = @_;2024 sub detectTypeChange($$$$$) 2025 { 2026 my ($Ct1, $Ct2, $Type1_Id, $Type2_Id, $Prefix) = @_; 1872 2027 my %LocalProblems = (); 1873 2028 … … 1878 2033 my $Type2_Name = $Type2->{"Name"}; 1879 2034 2035 my $Type1_Show = $Type1_Name; 2036 my $Type2_Show = $Type2_Name; 2037 2038 if(defined $Ct1->{"GenericParam"} 2039 and defined $Ct1->{"GenericParam"}{$Type1_Name}) 2040 { 2041 $Type1_Name = getTypeName($Ct1->{"GenericParam"}{$Type1_Name}, 1); 2042 $Type1_Show .= " extends ".$Type1_Name; 2043 } 2044 2045 if(defined $Ct2->{"GenericParam"} 2046 and defined $Ct2->{"GenericParam"}{$Type2_Name}) 2047 { 2048 $Type2_Name = getTypeName($Ct2->{"GenericParam"}{$Type2_Name}, 2); 2049 $Type2_Show .= " extends ".$Type2_Name; 2050 } 2051 1880 2052 my $Type1_Base = undef; 1881 2053 my $Type2_Base = undef; … … 1897 2069 return () if(not $Type1_Name or not $Type2_Name); 1898 2070 return () if(not $Type1_Base->{"Name"} or not $Type2_Base->{"Name"}); 2071 1899 2072 if($Type1_Base->{"Name"} ne $Type2_Base->{"Name"} and $Type1_Name eq $Type2_Name) 1900 2073 {# base type change … … 1906 2079 {# type change 1907 2080 %{$LocalProblems{"Changed_".$Prefix."_Type"}}=( 1908 "Old_Value"=>$Type1_ Name,1909 "New_Value"=>$Type2_ Name);2081 "Old_Value"=>$Type1_Show, 2082 "New_Value"=>$Type2_Show); 1910 2083 } 1911 2084 return %LocalProblems; … … 1953 2126 # settings 1954 2127 my ($Full, $Html, $Simple, $Italic, $Color, 1955 $ShowParams, $ShowClass, $ShowAttr, $Desc, $Target) = (0, 0, 0, 0, 0, 0, 0, 0, 0, undef); 2128 $ShowParams, $ShowClass, $ShowAttr, $Desc, 2129 $ShowReturn, $Target) = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, undef); 1956 2130 1957 2131 if($Kind=~/Full/) { … … 1985 2159 $Desc = 1; 1986 2160 } 2161 if($Kind=~/Return/) { 2162 $ShowReturn = 1; 2163 } 1987 2164 1988 2165 if(not defined $MethodInfo{$LVer}{$Method}{"ShortName"}) 1989 2166 { # from java.lang.Object 1990 if($Html or $Simple) {2167 if($Html) { 1991 2168 return specChars($Method); 1992 2169 } … … 1996 2173 } 1997 2174 1998 my $Signature = $MethodInfo{$LVer}{$Method}{"ShortName"}; 2175 my $Signature = ""; 2176 2177 my $ShortName = $MethodInfo{$LVer}{$Method}{"ShortName"}; 2178 2179 if($Html) { 2180 $ShortName = specChars($ShortName); 2181 } 2182 2183 $Signature .= $ShortName; 2184 1999 2185 if($Full or $ShowClass) 2000 2186 { … … 2138 2324 } 2139 2325 } 2140 2326 } 2327 2328 if($Full or $ShowReturn) 2329 { 2141 2330 if(my $ReturnId = $MethodInfo{$LVer}{$Method}{"Return"}) 2142 2331 { … … 2151 2340 } 2152 2341 2153 if($Simple) { 2342 if($Desc) { 2343 $Signature = "<b>".specChars($RName)."</b> ".$Signature; 2344 } 2345 elsif($Simple) { 2154 2346 $Signature .= " <b>:</b> ".specChars($RName); 2155 2347 } … … 2161 2353 } 2162 2354 } 2163 2355 } 2356 2357 if($Full) 2358 { 2164 2359 if(not $In::Opt{"SkipDeprecated"}) 2165 2360 { … … 2321 2516 "Warnings"=>0, 2322 2517 "Affected"=>0); 2518 2519 # check rules 2520 foreach my $Method (sort keys(%CompatProblems)) 2521 { 2522 foreach my $Kind (keys(%{$CompatProblems{$Method}})) 2523 { 2524 if(not defined $CompatRules{"Binary"}{$Kind} and not defined $CompatRules{"Source"}{$Kind}) 2525 { # unknown rule 2526 if(not $UnknownRules{$Level}{$Kind}) 2527 { # only one warning 2528 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")"); 2529 $UnknownRules{$Level}{$Kind}=1; 2530 } 2531 } 2532 } 2533 } 2323 2534 2324 2535 foreach my $Method (sort keys(%CompatProblems)) … … 2614 2825 $META_DATA .= "tool_version:$TOOL_VERSION"; 2615 2826 $Problem_Summary .= "</table>\n"; 2616 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA); 2827 2828 my $AnyChanged = ($Added or $Removed or $M_Problems_High or $M_Problems_Medium or $M_Problems_Low or 2829 $T_Problems_High or $T_Problems_Medium or $T_Problems_Low or $M_Other or $T_Other); 2830 2831 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA, $AnyChanged); 2617 2832 } 2618 2833 … … 2710 2925 } 2711 2926 2712 my @SortedMethods = sort {lc($MethodInfo{2}{$a}{"Signature"}) cmp lc($MethodInfo{2}{$b}{"Signature"})} keys(%{$NameSpace_Method{$NameSpace}});2927 my @SortedMethods = sort {lc($MethodInfo{2}{$a}{"Signature"}) cmp lc($MethodInfo{2}{$b}{"Signature"})} sort keys(%{$NameSpace_Method{$NameSpace}}); 2713 2928 foreach my $Method (@SortedMethods) 2714 2929 { … … 2814 3029 } 2815 3030 2816 my @SortedMethods = sort {lc($MethodInfo{1}{$a}{"Signature"}) cmp lc($MethodInfo{1}{$b}{"Signature"})} keys(%{$NameSpace_Method{$NameSpace}});3031 my @SortedMethods = sort {lc($MethodInfo{1}{$a}{"Signature"}) cmp lc($MethodInfo{1}{$b}{"Signature"})} sort keys(%{$NameSpace_Method{$NameSpace}}); 2817 3032 foreach my $Method (@SortedMethods) 2818 3033 { … … 2929 3144 } 2930 3145 2931 sub applyMacroses($$$$$ )2932 { 2933 my ($Level, $ Kind, $Content, $Problem, $AddAttr) = @_;3146 sub applyMacroses($$$$$$) 3147 { 3148 my ($Level, $Subj, $Kind, $Content, $Problem, $AddAttr) = @_; 2934 3149 2935 3150 $Content = addMarkup($Content); … … 2977 3192 $Fmt = "HTML|Desc"; 2978 3193 } 3194 } 3195 3196 if($Subj eq "Change") { 3197 $Fmt .= "|Return"; 2979 3198 } 2980 3199 … … 3062 3281 } 3063 3282 3064 my @SortedMethods = sort {lc($MethodInfo{1}{$a}{"Signature"}) cmp lc($MethodInfo{1}{$b}{"Signature"})} keys(%{$NameSpace_Method{$NameSpace}});3283 my @SortedMethods = sort {lc($MethodInfo{1}{$a}{"Signature"}) cmp lc($MethodInfo{1}{$b}{"Signature"})} sort keys(%{$NameSpace_Method{$NameSpace}}); 3065 3284 foreach my $Method (@SortedMethods) 3066 3285 { … … 3078 3297 my $ProblemAttr = $MethodChanges{$Method}{$Kind}{$Loc}; 3079 3298 3080 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr))3299 if(my $Change = applyMacroses($Level, "Change", $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr)) 3081 3300 { 3082 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr);3301 my $Effect = applyMacroses($Level, "Effect", $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr); 3083 3302 $METHOD_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n"; 3084 3303 $ProblemNum += 1; … … 3233 3452 my $ProblemAttr = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}; 3234 3453 3235 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr))3454 if(my $Change = applyMacroses($Level, "Change", $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $ProblemAttr, \%AddAttr)) 3236 3455 { 3237 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr);3456 my $Effect = applyMacroses($Level, "Effect", $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, $ProblemAttr, \%AddAttr); 3238 3457 3239 3458 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n"; … … 3587 3806 my $Description = "Compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions"; 3588 3807 3589 my ($BSummary, $BMetaData ) = getSummary("Binary");3590 my ($SSummary, $SMetaData ) = getSummary("Source");3591 3592 my $Report = "<!-\- $BMetaData -\->\n<!-\- $SMetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts )."<body><a name='Source'></a><a name='Binary'></a><a name='Top'></a>";3808 my ($BSummary, $BMetaData, $BAnyChanged) = getSummary("Binary"); 3809 my ($SSummary, $SMetaData, $SAnyChanged) = getSummary("Source"); 3810 3811 my $Report = "<!-\- $BMetaData -\->\n<!-\- $SMetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts, ($BAnyChanged or $SAnyChanged))."<body><a name='Source'></a><a name='Binary'></a><a name='Top'></a>"; 3593 3812 3594 3813 $Report .= getReportHeader("Join"); … … 3608 3827 else 3609 3828 { 3610 my ($Summary, $MetaData ) = getSummary($Level);3829 my ($Summary, $MetaData, $AnyChanged) = getSummary($Level); 3611 3830 3612 3831 my $Title = $In::Opt{"TargetTitle"}.": ".$In::Desc{1}{"Version"}." to ".$In::Desc{2}{"Version"}." ".lc($Level)." compatibility report"; … … 3614 3833 my $Description = "$Level compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions"; 3615 3834 3616 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts )."<body><a name='Top'></a>";3835 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Level, $Title, $Keywords, $Description, $CssStyles, $JScripts, $AnyChanged)."<body><a name='Top'></a>"; 3617 3836 $Report .= getReportHeader($Level)."\n".$Summary."\n"; 3618 3837 $Report .= getReportAdded($Level).getReportRemoved($Level); … … 3667 3886 } 3668 3887 3669 sub composeHTML_Head($$$$$$ )3670 { 3671 my ($Level, $Title, $Keywords, $Description, $Styles, $Scripts ) = @_;3888 sub composeHTML_Head($$$$$$$) 3889 { 3890 my ($Level, $Title, $Keywords, $Description, $Styles, $Scripts, $AnyChanged) = @_; 3672 3891 3673 3892 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; … … 3678 3897 $Head .= "<meta name=\"description\" content=\"$Description\" />\n"; 3679 3898 3899 if(not $AnyChanged) { 3900 $Head .= "<meta name=\"robots\" content=\"noindex\" />\n"; 3901 } 3902 3680 3903 my $RPath = getReportPath($Level); 3681 3904 … … 3749 3972 } 3750 3973 3751 my $ClassId = $MethodInfo{2}{$Method}{"Class"}; 3752 my $CName = getTypeName($ClassId, 2); 3974 my $Class = getType($MethodInfo{2}{$Method}{"Class"}, 2); 3753 3975 3754 $CheckedTypes{$C Name} = 1;3976 $CheckedTypes{$Class->{"Name"}} = 1; 3755 3977 $CheckedMethods{$Method} = 1; 3756 3978 3757 3979 if(not $MethodInfo{2}{$Method}{"Constructor"} 3758 and my $Overridden = findMethod($Method, 2, $C Name, 2))3980 and my $Overridden = findMethod($Method, 2, $Class->{"Name"}, 2)) 3759 3981 { 3760 3982 if(defined $MethodInfo{1}{$Overridden} 3761 and getTypeType($ClassId, 2) eq "class" and $TName_Tid{1}{$CName}) 3983 and $Class->{"Type"} eq "class" 3984 and ($TName_Tid{1}{$Class->{"Name"}} or $TName_Tid_Generic{1}{getGeneric($Class->{"Name"})})) 3762 3985 { # class should exist in previous version 3763 3986 %{$CompatProblems{$Overridden}{"Class_Overridden_Method"}{"this.".getSFormat($Method)}}=( 3764 "Type_Name"=>$C Name,3987 "Type_Name"=>$Class->{"Name"}, 3765 3988 "Target"=>$MethodInfo{2}{$Method}{"Signature"}, 3766 3989 "Old_Value"=>$Overridden, … … 3769 3992 } 3770 3993 if($MethodInfo{2}{$Method}{"Abstract"}) { 3771 $AddedMethod_Abstract{$C Name}{$Method} = 1;3994 $AddedMethod_Abstract{$Class->{"Name"}}{$Method} = 1; 3772 3995 } 3773 3996 3774 %{$CompatProblems{$Method}{"Added_Method"}{""}}=(); 3997 if(not ($MethodInfo{2}{$Method}{"Access"} eq "protected" and $Class->{"Final"})) { 3998 %{$CompatProblems{$Method}{"Added_Method"}{""}} = (); 3999 } 3775 4000 3776 4001 if(not $MethodInfo{2}{$Method}{"Constructor"}) 3777 4002 { 3778 if(getTypeName($MethodInfo{2}{$Method}{"Return"}, 2) ne "void" 3779 and my $VoidMethod = checkVoidMethod($Method)) 4003 my $VoidMethod = checkVoidMethod($Method); 4004 my $ReturnType = getTypeName($MethodInfo{2}{$Method}{"Return"}, 2); 4005 4006 if(defined $Class->{"GenericParam"} 4007 and defined $Class->{"GenericParam"}{$ReturnType}) { 4008 $ReturnType = getTypeName($Class->{"GenericParam"}{$ReturnType}, 2); 4009 } 4010 4011 if(defined $MethodInfo{1}{$VoidMethod} 4012 and $ReturnType ne "void") 4013 { # return value type changed from void 4014 $ChangedReturnFromVoid{$VoidMethod} = 1; 4015 $ChangedReturnFromVoid{$Method} = 1; 4016 4017 %{$CompatProblems{$VoidMethod}{"Changed_Method_Return_From_Void"}{""}}=( 4018 "New_Value"=>getTypeName($MethodInfo{2}{$Method}{"Return"}, 2) 4019 ); 4020 } 4021 elsif(my $OldMethod = $OldMethodSignature{getBaseSignature($Method)}) 3780 4022 { 3781 if(defined $MethodInfo{1}{$VoidMethod}) 3782 { # return value type changed from "void" to 3783 $ChangedReturnFromVoid{$VoidMethod} = 1; 3784 $ChangedReturnFromVoid{$Method} = 1; 4023 if($OldMethod ne $Method) 4024 { 4025 my $OldReturnType = getTypeName($MethodInfo{1}{$OldMethod}{"Return"}, 1); 3785 4026 3786 %{$CompatProblems{$VoidMethod}{"Changed_Method_Return_From_Void"}{""}}=( 3787 "New_Value"=>getTypeName($MethodInfo{2}{$Method}{"Return"}, 2) 4027 %{$CompatProblems{$OldMethod}{"Changed_Method_Return"}{""}}=( 4028 "Old_Value"=>$OldReturnType, 4029 "New_Value"=>$ReturnType 3788 4030 ); 3789 4031 } … … 3804 4046 } 3805 4047 3806 my $ClassId = $MethodInfo{1}{$Method}{"Class"}; 3807 my $CName = getTypeName($ClassId, 1); 4048 my $Class = getType($MethodInfo{1}{$Method}{"Class"}, 1); 3808 4049 3809 $CheckedTypes{$C Name} = 1;4050 $CheckedTypes{$Class->{"Name"}} = 1; 3810 4051 $CheckedMethods{$Method} = 1; 3811 4052 3812 4053 if(not $MethodInfo{1}{$Method}{"Constructor"} 3813 and my $MovedUp = findMethod($Method, 1, $CName, 2)) 3814 { 3815 if(getTypeType($ClassId, 1) eq "class" 3816 and not $MethodInfo{1}{$Method}{"Abstract"} and $TName_Tid{2}{$CName}) 4054 and my $MovedUp = findMethod($Method, 1, $Class->{"Name"}, 2)) 4055 { 4056 if($Class->{"Type"} eq "class" 4057 and not $MethodInfo{1}{$Method}{"Abstract"} 4058 and ($TName_Tid{2}{$Class->{"Name"}} or $TName_Tid_Generic{2}{getGeneric($Class->{"Name"})})) 3817 4059 {# class should exist in newer version 3818 4060 %{$CompatProblems{$Method}{"Class_Method_Moved_Up_Hierarchy"}{"this.".getSFormat($MovedUp)}}=( 3819 "Type_Name"=>$C Name,4061 "Type_Name"=>$Class->{"Name"}, 3820 4062 "Target"=>$MethodInfo{2}{$MovedUp}{"Signature"}, 3821 4063 "Old_Value"=>$Method, … … 3826 4068 { 3827 4069 if($MethodInfo{1}{$Method}{"Abstract"}) { 3828 $RemovedMethod_Abstract{$CName}{$Method} = 1; 3829 } 3830 %{$CompatProblems{$Method}{"Removed_Method"}{""}}=(); 4070 $RemovedMethod_Abstract{$Class->{"Name"}}{$Method} = 1; 4071 } 4072 4073 if(not ($MethodInfo{1}{$Method}{"Access"} eq "protected" and $Class->{"Final"})) { 4074 %{$CompatProblems{$Method}{"Removed_Method"}{""}} = (); 4075 } 3831 4076 } 3832 4077 } … … 3930 4175 if(cmpVersions($APIVer, $API_DUMP_VERSION)>0) 3931 4176 { # future formats 3932 exitStatus("Dump_Version", "the versions of the API dump is newer than version of the tool"); 3933 } 3934 } 3935 3936 if(cmpVersions($APIVer, $API_DUMP_VERSION_MIN)<0) { 3937 exitStatus("Dump_Version", "the version of the API dump is too old and unsupported anymore, please regenerate it"); 4177 exitStatus("Dump_Version", "version of the API dump is newer than version of the tool"); 4178 } 4179 4180 if(cmpVersions($APIVer, $API_DUMP_VERSION)<0) 4181 { # old formats 4182 printMsg("WARNING", "version of the API dump is older than version of the tool"); 4183 } 4184 } 4185 4186 if(cmpVersions($APIVer, $API_DUMP_VERSION_MIN)<0) 4187 { # obsolete formats 4188 exitStatus("Dump_Version", "version of the API dump is too old and unsupported anymore, please regenerate it"); 3938 4189 } 3939 4190 … … 4224 4475 chdir($UnpackDir); 4225 4476 system("$UnzipCmd \"$Path\" >contents.txt"); 4477 chdir($In::Opt{"OrigDir"}); 4226 4478 if($?) { 4227 4479 exitStatus("Error", "can't extract \'$Path\'"); 4228 4480 } 4229 chdir($In::Opt{"OrigDir"});4481 4230 4482 my @Contents = (); 4231 4483 foreach (split("\n", readFile("$UnpackDir/contents.txt"))) … … 4259 4511 } 4260 4512 my @Contents = qx/$TarCmd -xvf "$Dir\\$FileName.tar"/; 4513 chdir($In::Opt{"OrigDir"}); 4261 4514 if($? or not @Contents) { 4262 4515 exitStatus("Error", "can't extract \'$Path\'"); 4263 4516 } 4264 chdir($In::Opt{"OrigDir"});4265 4517 unlink($Dir."/".$FileName.".tar"); 4266 4518 chomp $Contents[0]; … … 4275 4527 chdir($UnpackDir); 4276 4528 my @Contents = qx/$TarCmd -xvzf "$Path" 2>&1/; 4529 chdir($In::Opt{"OrigDir"}); 4277 4530 if($? or not @Contents) { 4278 4531 exitStatus("Error", "can't extract \'$Path\'"); 4279 4532 } 4280 chdir($In::Opt{"OrigDir"});4281 4533 $Contents[0]=~s/^x //; # OS X 4282 4534 chomp $Contents[0]; … … 4308 4560 if($?) 4309 4561 { # cannot allocate memory (or other problems with "zip") 4310 unlink($Path);4562 chdir($In::Opt{"OrigDir"}); 4311 4563 exitStatus("Error", "can't pack the API dump: ".$!); 4312 4564 } … … 4326 4578 } 4327 4579 my $Pkg = abs_path($To)."/".$Name.".tar.gz"; 4328 unlink($Pkg); 4329 chdir($From); 4330 system($TarCmd, "-czf", $Pkg, $Name); 4580 if(-e $Pkg) { 4581 unlink($Pkg); 4582 } 4583 system($TarCmd, "-C", $From, "-czf", $Pkg, $Name); 4331 4584 if($?) 4332 4585 { # cannot allocate memory (or other problems with "tar") 4333 unlink($Path);4334 4586 exitStatus("Error", "can't pack the API dump: ".$!); 4335 4587 } 4336 chdir($In::Opt{"OrigDir"});4337 4588 unlink($Path); 4338 4589 return $To."/".$Name.".tar.gz"; … … 4768 5019 { 4769 5020 detectDefaultPaths("bin", undef); 5021 loadModule("APIDump"); 5022 4770 5023 readArchive(0, $ClientPath) 4771 5024 } … … 4785 5038 4786 5039 my $Count = 0; 4787 foreach my $Method (keys(%{$MethodInfo{1}})) { 5040 foreach my $Method (keys(%{$MethodInfo{1}})) 5041 { 4788 5042 $Count += methodFilter($Method, 1); 4789 5043 }
Note:
See TracChangeset
for help on using the changeset viewer.