Ensure old tab state is cleared between iterations of run-benchmark
[WebKit-https.git] / Tools / Scripts / check-Xcode-source-file-types
1 #!/usr/bin/env perl
2
3 # Copyright (C) 2007, 2008, 2009, 2010 Apple Inc.  All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
9 # 1.  Redistributions of source code must retain the above copyright
10 #     notice, this list of conditions and the following disclaimer. 
11 # 2.  Redistributions in binary form must reproduce the above copyright
12 #     notice, this list of conditions and the following disclaimer in the
13 #     documentation and/or other materials provided with the distribution. 
14 #
15 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26 # Script to check that source file extensions match file types in Xcode project.pbxproj files.
27
28 # TODO
29 # - Add support for file types other than source code files.
30 # - Can't differentiate between sourcecode.c.h and sourcecode.cpp.h.
31 #   (Hint: Use gcc -x c/objective-c/c++/objective-c++ -E.  It will
32 #   take time to check each header using gcc, so make it a switch.)
33
34 use strict;
35 use warnings;
36
37 use File::Basename;
38 use File::Spec;
39 use File::Temp qw(tempfile);
40 use Getopt::Long;
41
42 # Map of Xcode file types to file extensions.
43 my %typeExtensionMap = qw(
44     sourcecode.c.c        .c
45     sourcecode.c.h        .h
46     sourcecode.c.objc     .m
47     sourcecode.cpp.h      .h
48     sourcecode.cpp.cpp    .cpp
49     sourcecode.cpp.objcpp .mm
50     sourcecode.exports    .exp
51     sourcecode.javascript .js
52     sourcecode.make       .make
53     sourcecode.mig        .defs
54     sourcecode.yacc       .y
55 );
56
57 # Map of file extensions to Xcode file types.
58 my %extensionTypeMap = map { $typeExtensionMap{$_} => $_ } keys %typeExtensionMap;
59 $extensionTypeMap{'.h'} = 'sourcecode.c.h'; # See TODO list.
60
61 my $shouldFixIssues = 0;
62 my $printWarnings = 1;
63 my $showHelp;
64
65 my $getOptionsResult = GetOptions(
66     'f|fix'          => \$shouldFixIssues,
67     'h|help'         => \$showHelp,
68     'w|warnings!'    => \$printWarnings,
69 );
70
71 if (scalar(@ARGV) == 0 && !$showHelp) {
72     print STDERR "ERROR: No Xcode project files (project.pbxproj) listed on command-line.\n";
73     undef $getOptionsResult;
74 }
75
76 if (!$getOptionsResult || $showHelp) {
77     print STDERR <<__END__;
78 Usage: @{[ basename($0) ]} [options] path/to/project.pbxproj [path/to/project.pbxproj ...]
79   -f|--fix            fix mismatched types in Xcode project file
80   -h|--help           show this help message
81   -w|--[no-]warnings  show or suppress warnings (default: show warnings)
82 __END__
83     exit 1;
84 }
85
86 for my $projectFile (@ARGV) {
87     my $issuesFound = 0;
88     my $issuesFixed = 0;
89
90     if (basename($projectFile) =~ /\.xcodeproj$/) {
91         $projectFile = File::Spec->catfile($projectFile, "project.pbxproj");
92     }
93
94     if (basename($projectFile) ne "project.pbxproj") {
95         print STDERR "WARNING: Not an Xcode project file: $projectFile\n" if $printWarnings;
96         next;
97     }
98
99     open(IN, "< $projectFile") || die "Could not open $projectFile: $!";
100
101     my ($OUT, $tempFileName);
102     if ($shouldFixIssues) {
103         ($OUT, $tempFileName) = tempfile(
104             basename($projectFile) . "-XXXXXXXX",
105             DIR => dirname($projectFile),
106             UNLINK => 0,
107         );
108
109         # Clean up temp file in case of die()
110         $SIG{__DIE__} = sub {
111             close(IN);
112             close($OUT);
113             unlink($tempFileName);
114         };
115     }
116
117     # Fast-forward to "Begin PBXFileReference section".
118     while (my $line = <IN>) {
119         print $OUT $line if $shouldFixIssues;
120         last if $line =~ m#^\Q/* Begin PBXFileReference section */\E$#;
121     }
122
123     while (my $line = <IN>) {
124         if ($line =~ m#^\Q/* End PBXFileReference section */\E$#) {
125             print $OUT $line if $shouldFixIssues;
126             last;
127         }
128
129         if ($line =~ m#^\s*[A-Z0-9]{24} /\* (.+) \*/\s+=\s+\{.*\s+explicitFileType = (sourcecode[^;]*);.*\s+path = ([^;]+);.*\};$#) {
130             my $fileName = $1;
131             my $fileType = $2;
132             my $filePath = $3;
133             my (undef, undef, $fileExtension) = map { lc($_) } fileparse(basename($filePath), qr{\.[^.]+$});
134
135             if (!exists $typeExtensionMap{$fileType}) {
136                 $issuesFound++;
137                 print STDERR "WARNING: Unknown file type '$fileType' for file '$filePath'.\n" if $printWarnings;
138             } elsif ($typeExtensionMap{$fileType} ne $fileExtension) {
139                 $issuesFound++;
140                 print STDERR "WARNING: Incorrect file type '$fileType' for file '$filePath'.\n" if $printWarnings;
141                 $line =~ s/(\s+)explicitFileType( = )(sourcecode[^;]*);/$1lastKnownFileType$2$extensionTypeMap{$fileExtension};/;
142                 $issuesFixed++ if $shouldFixIssues;
143             }
144         }
145
146         print $OUT $line if $shouldFixIssues;
147     }
148
149     # Output the rest of the file.
150     print $OUT <IN> if $shouldFixIssues;
151
152     close(IN);
153
154     if ($shouldFixIssues) {
155         close($OUT);
156
157         unlink($projectFile) || die "Could not delete $projectFile: $!";
158         rename($tempFileName, $projectFile) || die "Could not rename $tempFileName to $projectFile: $!";
159     }
160
161     if ($printWarnings) {
162         printf STDERR "%s issues found for $projectFile.\n", ($issuesFound ? $issuesFound : "No");
163         print STDERR "$issuesFixed issues fixed for $projectFile.\n" if $issuesFixed && $shouldFixIssues;
164         print STDERR "NOTE: Open $projectFile in Xcode to let it have its way with the file.\n" if $issuesFixed;
165         print STDERR "\n";
166     }
167 }
168
169 exit 0;