Ignore:
Timestamp:
2017-09-17T15:47:18+02:00 (4 years ago)
Author:
Don-vip
Message:

update to JAPICC 2.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tools/japicc/japi-compliance-checker.pl

    r11682 r12872  
    11#!/usr/bin/perl
    22###########################################################################
    3 # Java API Compliance Checker (JAPICC) 2.1
     3# Java API Compliance Checker (JAPICC) 2.3
    44# A tool for checking backward compatibility of a Java library API
    55#
     
    4343use Data::Dumper;
    4444
    45 my $TOOL_VERSION = "2.1";
    46 my $API_DUMP_VERSION = "2.1";
    47 my $API_DUMP_VERSION_MIN = "2.0";
     45my $TOOL_VERSION = "2.3";
     46my $API_DUMP_VERSION = "2.2";
     47my $API_DUMP_VERSION_MIN = "2.2";
    4848
    4949# Internal modules
     
    110110  "skip-internal-types=s" => \$In::Opt{"SkipInternalTypes"},
    111111  "dump|dump-api=s" => \$In::Opt{"DumpAPI"},
     112  "check-packages=s" => \$In::Opt{"CheckPackages"},
    112113  "classes-list=s" => \$In::Opt{"ClassListPath"},
    113114  "annotations-list=s" => \$In::Opt{"AnnotationsListPath"},
     
    291292 
    292293  -skip-internal-packages PATTERN
    293       Do not check packages matched by the pattern.
     294      Do not check packages matched by the regular expression.
    294295 
    295296  -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.
    297300 
    298301  -dump|-dump-api PATH
    299302      Dump library API to gzipped TXT format file. You can transfer it
    300303      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 
    303311  -classes-list PATH
    304312      This option allows to specify a file with a list
     
    441449#Aliases
    442450my (%MethodInfo, %TypeInfo, %TName_Tid) = ();
     451
     452my %TName_Tid_Generic = ();
    443453
    444454#Separate checked and unchecked exceptions
     
    522532my %LibArchives;
    523533my %Class_Methods;
     534my %Class_Methods_Generic;
    524535my %Class_AbstractMethods;
    525536my %Class_Fields;
     
    530541my %CheckedMethods;
    531542my %MethodUsed;
     543my %OldMethodSignature;
    532544
    533545#Merging
     
    537549my %CompatRules;
    538550my %IncompleteRules;
     551my %UnknownRules;
    539552
    540553#Report
     
    623636    {
    624637        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);
    626640       
    627641        if($Type1->{"Type"}!~/class|interface/) {
     
    634648        }
    635649       
    636         if(not classFilter($Type1, 1, 0)) {
     650        if(not classFilter($Type1, 1, 1)) {
    637651            next;
    638652        }
    639653       
    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
    642721        { # classes and interfaces with public methods
    643722            foreach my $Method (keys(%{$Class_Methods{1}{$ClassName}}))
     
    686765       
    687766        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)
    690778        { # classes and interfaces with public static fields
    691779            if(not defined $Class_Methods{1}{$ClassName})
     
    869957    return {} if(not $Type1{"Name"} or not $Type2{"Name"});
    870958    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)) {
    874968        return {};
    875969    }
     
    9251019    pushType($Type1_Id, $Type2_Id);
    9261020   
    927     foreach my $AddedMethod (keys(%{$AddedMethod_Abstract{$Type1{"Name"}}}))
     1021    foreach my $AddedMethod (keys(%{$AddedMethod_Abstract{$Type2{"Name"}}}))
    9281022    {
    9291023        if($Type1{"Type"} eq "class")
     
    10001094        my $SuperClassName2 = $SuperClass2->{"Name"};
    10011095       
     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       
    10021106        if($SuperClassName2 ne $SuperClassName1)
    10031107        {
    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}}))
    10101113                {
    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"}))
    10141115                    {
    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);
    10291121                    }
    10301122                    else
    10311123                    {
    1032                         %{$SubProblems{"Added_Super_Class"}{""}} = (
     1124                        %{$SubProblems{"Abstract_Class_Added_Super_Abstract_Class"}{""}} = (
    10331125                            "Type_Name"=>$Type1{"Name"},
    10341126                            "Target"=>$SuperClassName2);
    10351127                    }
    10361128                }
    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
    10441130                {
    1045                     %{$SubProblems{"Removed_Super_Class"}{""}} = (
     1131                    %{$SubProblems{"Added_Super_Class"}{""}} = (
    10461132                        "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);
    10491141            }
    10501142            else
     
    13371429        }
    13381430       
    1339         my %Sub_SubChanges = detectTypeChange($FieldType1_Id, $FieldType2_Id, "Field");
     1431        my %Sub_SubChanges = detectTypeChange(\%Type1, \%Type2, $FieldType1_Id, $FieldType2_Id, "Field");
    13401432        foreach my $Sub_SubProblemType (keys(%Sub_SubChanges))
    13411433        {
     
    14601552{
    14611553    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    }
    14631564   
    14641565    if($ClassId)
     
    15171618{
    15181619    my ($Method, $ClassName, $ClassVersion) = @_;
     1620   
    15191621    my $TargetSuffix = getMSuffix($Method);
    15201622    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 {
    15231634        return undef;
    15241635    }
    15251636   
    1526     foreach my $Candidate (sort keys(%{$Class_Methods{$ClassVersion}{$ClassName}}))
     1637    foreach my $Candidate (sort @Candidates)
    15271638    { # search for method with the same parameters suffix
    15281639        next if($MethodInfo{$ClassVersion}{$Candidate}{"Constructor"});
     1640       
    15291641        if($TargetSuffix eq getMSuffix($Candidate))
    15301642        {
     
    15381650}
    15391651
     1652sub getBaseSignature($)
     1653{
     1654    my $Method = $_[0];
     1655    $Method=~s/\)(.+)\Z/\)/g;
     1656    return $Method;
     1657}
     1658
    15401659sub prepareData($)
    15411660{
     
    15581677        $TName_Tid{$LVer}{$TName} = $TypeId;
    15591678       
     1679        if(defined $TypeAttr->{"Archive"})
     1680        { # declaration
     1681            $TName_Tid_Generic{$LVer}{getGeneric($TName)} = $TypeId;
     1682        }
     1683       
    15601684        if(not $TypeAttr->{"Dep"})
    15611685        {
     
    15901714            my $CName = getTypeName($ClassId, $LVer);
    15911715            $Class_Methods{$LVer}{$CName}{$Method} = 1;
     1716            $Class_Methods_Generic{$LVer}{getGeneric($CName)}{$Method} = 1;
     1717           
    15921718            if($MAttr->{"Abstract"}) {
    15931719                $Class_AbstractMethods{$LVer}{$CName}{$Method} = 1;
     
    16031729                registerUsage($MAttr->{"Return"}, $LVer);
    16041730            }
     1731        }
     1732       
     1733        if($LVer==1 and not $MAttr->{"Constructor"}
     1734        and my $BaseSign = getBaseSignature($Method)) {
     1735            $OldMethodSignature{$BaseSign} = $Method;
    16051736        }
    16061737    }
     
    18571988    # checking type declaration changes
    18581989    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   
    18592014    foreach my $SubProblemType (keys(%{$SubProblems}))
    18602015    {
     
    18672022}
    18682023
    1869 sub detectTypeChange($$$)
    1870 {
    1871     my ($Type1_Id, $Type2_Id, $Prefix) = @_;
     2024sub detectTypeChange($$$$$)
     2025{
     2026    my ($Ct1, $Ct2, $Type1_Id, $Type2_Id, $Prefix) = @_;
    18722027    my %LocalProblems = ();
    18732028   
     
    18782033    my $Type2_Name = $Type2->{"Name"};
    18792034   
     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   
    18802052    my $Type1_Base = undef;
    18812053    my $Type2_Base = undef;
     
    18972069    return () if(not $Type1_Name or not $Type2_Name);
    18982070    return () if(not $Type1_Base->{"Name"} or not $Type2_Base->{"Name"});
     2071   
    18992072    if($Type1_Base->{"Name"} ne $Type2_Base->{"Name"} and $Type1_Name eq $Type2_Name)
    19002073    {# base type change
     
    19062079    {# type change
    19072080        %{$LocalProblems{"Changed_".$Prefix."_Type"}}=(
    1908             "Old_Value"=>$Type1_Name,
    1909             "New_Value"=>$Type2_Name);
     2081            "Old_Value"=>$Type1_Show,
     2082            "New_Value"=>$Type2_Show);
    19102083    }
    19112084    return %LocalProblems;
     
    19532126    # settings
    19542127    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);
    19562130   
    19572131    if($Kind=~/Full/) {
     
    19852159        $Desc = 1;
    19862160    }
     2161    if($Kind=~/Return/) {
     2162        $ShowReturn = 1;
     2163    }
    19872164   
    19882165    if(not defined $MethodInfo{$LVer}{$Method}{"ShortName"})
    19892166    { # from java.lang.Object
    1990         if($Html or $Simple) {
     2167        if($Html) {
    19912168            return specChars($Method);
    19922169        }
     
    19962173    }
    19972174   
    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   
    19992185    if($Full or $ShowClass)
    20002186    {
     
    21382324            }
    21392325        }
    2140        
     2326    }
     2327   
     2328    if($Full or $ShowReturn)
     2329    {
    21412330        if(my $ReturnId = $MethodInfo{$LVer}{$Method}{"Return"})
    21422331        {
     
    21512340            }
    21522341           
    2153             if($Simple) {
     2342            if($Desc) {
     2343                $Signature = "<b>".specChars($RName)."</b> ".$Signature;
     2344            }
     2345            elsif($Simple) {
    21542346                $Signature .= " <b>:</b> ".specChars($RName);
    21552347            }
     
    21612353            }
    21622354        }
    2163        
     2355    }
     2356   
     2357    if($Full)
     2358    {
    21642359        if(not $In::Opt{"SkipDeprecated"})
    21652360        {
     
    23212516        "Warnings"=>0,
    23222517        "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    }
    23232534   
    23242535    foreach my $Method (sort keys(%CompatProblems))
     
    26142825    $META_DATA .= "tool_version:$TOOL_VERSION";
    26152826    $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);
    26172832}
    26182833
     
    27102925                }
    27112926               
    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}});
    27132928                foreach my $Method (@SortedMethods)
    27142929                {
     
    28143029                }
    28153030               
    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}});
    28173032                foreach my $Method (@SortedMethods)
    28183033                {
     
    29293144}
    29303145
    2931 sub applyMacroses($$$$$)
    2932 {
    2933     my ($Level, $Kind, $Content, $Problem, $AddAttr) = @_;
     3146sub applyMacroses($$$$$$)
     3147{
     3148    my ($Level, $Subj, $Kind, $Content, $Problem, $AddAttr) = @_;
    29343149   
    29353150    $Content = addMarkup($Content);
     
    29773192                    $Fmt = "HTML|Desc";
    29783193                }
     3194            }
     3195           
     3196            if($Subj eq "Change") {
     3197                $Fmt .= "|Return";
    29793198            }
    29803199           
     
    30623281                }
    30633282               
    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}});
    30653284                foreach my $Method (@SortedMethods)
    30663285                {
     
    30783297                            my $ProblemAttr = $MethodChanges{$Method}{$Kind}{$Loc};
    30793298                           
    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))
    30813300                            {
    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);
    30833302                                $METHOD_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n";
    30843303                                $ProblemNum += 1;
     
    32333452                        my $ProblemAttr = $TypeChanges_Sev{$TypeName}{$Kind}{$Location};
    32343453                       
    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))
    32363455                        {
    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);
    32383457                           
    32393458                            $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n";
     
    35873806        my $Description = "Compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions";
    35883807       
    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>";
    35933812       
    35943813        $Report .= getReportHeader("Join");
     
    36083827    else
    36093828    {
    3610         my ($Summary, $MetaData) = getSummary($Level);
     3829        my ($Summary, $MetaData, $AnyChanged) = getSummary($Level);
    36113830       
    36123831        my $Title = $In::Opt{"TargetTitle"}.": ".$In::Desc{1}{"Version"}." to ".$In::Desc{2}{"Version"}." ".lc($Level)." compatibility report";
     
    36143833        my $Description = "$Level compatibility report for the ".$In::Opt{"TargetTitle"}." library between ".$In::Desc{1}{"Version"}." and ".$In::Desc{2}{"Version"}." versions";
    36153834       
    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>";
    36173836        $Report .= getReportHeader($Level)."\n".$Summary."\n";
    36183837        $Report .= getReportAdded($Level).getReportRemoved($Level);
     
    36673886}
    36683887
    3669 sub composeHTML_Head($$$$$$)
    3670 {
    3671     my ($Level, $Title, $Keywords, $Description, $Styles, $Scripts) = @_;
     3888sub composeHTML_Head($$$$$$$)
     3889{
     3890    my ($Level, $Title, $Keywords, $Description, $Styles, $Scripts, $AnyChanged) = @_;
    36723891   
    36733892    my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
     
    36783897    $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
    36793898   
     3899    if(not $AnyChanged) {
     3900        $Head .= "<meta name=\"robots\" content=\"noindex\" />\n";
     3901    }
     3902   
    36803903    my $RPath = getReportPath($Level);
    36813904   
     
    37493972            }
    37503973           
    3751             my $ClassId = $MethodInfo{2}{$Method}{"Class"};
    3752             my $CName = getTypeName($ClassId, 2);
     3974            my $Class = getType($MethodInfo{2}{$Method}{"Class"}, 2);
    37533975           
    3754             $CheckedTypes{$CName} = 1;
     3976            $CheckedTypes{$Class->{"Name"}} = 1;
    37553977            $CheckedMethods{$Method} = 1;
    37563978           
    37573979            if(not $MethodInfo{2}{$Method}{"Constructor"}
    3758             and my $Overridden = findMethod($Method, 2, $CName, 2))
     3980            and my $Overridden = findMethod($Method, 2, $Class->{"Name"}, 2))
    37593981            {
    37603982                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"})}))
    37623985                { # class should exist in previous version
    37633986                    %{$CompatProblems{$Overridden}{"Class_Overridden_Method"}{"this.".getSFormat($Method)}}=(
    3764                         "Type_Name"=>$CName,
     3987                        "Type_Name"=>$Class->{"Name"},
    37653988                        "Target"=>$MethodInfo{2}{$Method}{"Signature"},
    37663989                        "Old_Value"=>$Overridden,
     
    37693992            }
    37703993            if($MethodInfo{2}{$Method}{"Abstract"}) {
    3771                 $AddedMethod_Abstract{$CName}{$Method} = 1;
     3994                $AddedMethod_Abstract{$Class->{"Name"}}{$Method} = 1;
    37723995            }
    37733996           
    3774             %{$CompatProblems{$Method}{"Added_Method"}{""}}=();
     3997            if(not ($MethodInfo{2}{$Method}{"Access"} eq "protected" and $Class->{"Final"})) {
     3998                %{$CompatProblems{$Method}{"Added_Method"}{""}} = ();
     3999            }
    37754000           
    37764001            if(not $MethodInfo{2}{$Method}{"Constructor"})
    37774002            {
    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)})
    37804022                {
    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);
    37854026                       
    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
    37884030                        );
    37894031                    }
     
    38044046            }
    38054047           
    3806             my $ClassId = $MethodInfo{1}{$Method}{"Class"};
    3807             my $CName = getTypeName($ClassId, 1);
     4048            my $Class = getType($MethodInfo{1}{$Method}{"Class"}, 1);
    38084049           
    3809             $CheckedTypes{$CName} = 1;
     4050            $CheckedTypes{$Class->{"Name"}} = 1;
    38104051            $CheckedMethods{$Method} = 1;
    38114052           
    38124053            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"})}))
    38174059                {# class should exist in newer version
    38184060                    %{$CompatProblems{$Method}{"Class_Method_Moved_Up_Hierarchy"}{"this.".getSFormat($MovedUp)}}=(
    3819                         "Type_Name"=>$CName,
     4061                        "Type_Name"=>$Class->{"Name"},
    38204062                        "Target"=>$MethodInfo{2}{$MovedUp}{"Signature"},
    38214063                        "Old_Value"=>$Method,
     
    38264068            {
    38274069                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                }
    38314076            }
    38324077        }
     
    39304175        if(cmpVersions($APIVer, $API_DUMP_VERSION)>0)
    39314176        { # 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");
    39384189    }
    39394190   
     
    42244475        chdir($UnpackDir);
    42254476        system("$UnzipCmd \"$Path\" >contents.txt");
     4477        chdir($In::Opt{"OrigDir"});
    42264478        if($?) {
    42274479            exitStatus("Error", "can't extract \'$Path\'");
    42284480        }
    4229         chdir($In::Opt{"OrigDir"});
     4481       
    42304482        my @Contents = ();
    42314483        foreach (split("\n", readFile("$UnpackDir/contents.txt")))
     
    42594511            }
    42604512            my @Contents = qx/$TarCmd -xvf "$Dir\\$FileName.tar"/;
     4513            chdir($In::Opt{"OrigDir"});
    42614514            if($? or not @Contents) {
    42624515                exitStatus("Error", "can't extract \'$Path\'");
    42634516            }
    4264             chdir($In::Opt{"OrigDir"});
    42654517            unlink($Dir."/".$FileName.".tar");
    42664518            chomp $Contents[0];
     
    42754527            chdir($UnpackDir);
    42764528            my @Contents = qx/$TarCmd -xvzf "$Path" 2>&1/;
     4529            chdir($In::Opt{"OrigDir"});
    42774530            if($? or not @Contents) {
    42784531                exitStatus("Error", "can't extract \'$Path\'");
    42794532            }
    4280             chdir($In::Opt{"OrigDir"});
    42814533            $Contents[0]=~s/^x //; # OS X
    42824534            chomp $Contents[0];
     
    43084560        if($?)
    43094561        { # cannot allocate memory (or other problems with "zip")
    4310             unlink($Path);
     4562            chdir($In::Opt{"OrigDir"});
    43114563            exitStatus("Error", "can't pack the API dump: ".$!);
    43124564        }
     
    43264578        }
    43274579        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);
    43314584        if($?)
    43324585        { # cannot allocate memory (or other problems with "tar")
    4333             unlink($Path);
    43344586            exitStatus("Error", "can't pack the API dump: ".$!);
    43354587        }
    4336         chdir($In::Opt{"OrigDir"});
    43374588        unlink($Path);
    43384589        return $To."/".$Name.".tar.gz";
     
    47685019        {
    47695020            detectDefaultPaths("bin", undef);
     5021            loadModule("APIDump");
     5022           
    47705023            readArchive(0, $ClientPath)
    47715024        }
     
    47855038       
    47865039        my $Count = 0;
    4787         foreach my $Method (keys(%{$MethodInfo{1}})) {
     5040        foreach my $Method (keys(%{$MethodInfo{1}}))
     5041        {
    47885042            $Count += methodFilter($Method, 1);
    47895043        }
Note: See TracChangeset for help on using the changeset viewer.