WebKit Bugzilla
Attachment 348345 Details for
Bug 188754
: Tool to fix folders that should map to directories in Xcode project files
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch v3
bug-188754-20180828150034.patch (text/plain), 41.61 KB, created by
David Kilzer (:ddkilzer)
on 2018-08-28 15:00:35 PDT
(
hide
)
Description:
Patch v3
Filename:
MIME Type:
Creator:
David Kilzer (:ddkilzer)
Created:
2018-08-28 15:00:35 PDT
Size:
41.61 KB
patch
obsolete
>Subversion Revision: 235439 >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index f46457b441f05d6f56df62a86ae53163b1973908..96ae26ddc49d53f148cb888cdbb440781b1f8a9a 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,31 @@ >+2018-08-28 David Kilzer <ddkilzer@apple.com> >+ >+ Tool to fix folders that should map to directories in Xcode project files >+ <https://webkit.org/b/188754> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add new tidy-Xcode-project-file script. The -m|--map-folders >+ switch will clean up the Xcode project file to map folders to >+ directories on disk. Note that there may be some clean up >+ required for the script to update the project file. >+ >+ * Scripts/tidy-Xcode-project-file: Add. >+ (main): >+ (findGroupsToConvertToDirectory): >+ (loadXcodeProjectFile): >+ (mapFoldersToDirectories): >+ (parseChildrenFromGroup): >+ (parseFileReference): >+ (parseXcodeProjectFile): >+ (saveXcodeProjectFile): >+ (updateFoldersToDirectories): >+ * Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseChildrenFromGroup.pl: Add. >+ * Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseFileReference.pl: Add. >+ * Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseXcodeProjectFile.pl: Add. >+ * Scripts/webkitpy/style/checker.py: Ignore tabs in >+ tidy-Xcode-project-file unit tests. >+ > 2018-08-28 David Kilzer <ddkilzer@apple.com> > > Fix incorrect use of `sourceTree = "<group>";` for built products and frameworks in Xcode projects >diff --git a/Tools/Scripts/tidy-Xcode-project-file b/Tools/Scripts/tidy-Xcode-project-file >new file mode 100755 >index 0000000000000000000000000000000000000000..6f2a18068a06ca2b60498985fbb8cd6d9e9a64c0 >--- /dev/null >+++ b/Tools/Scripts/tidy-Xcode-project-file >@@ -0,0 +1,452 @@ >+#!/usr/bin/env perl >+ >+# Copyright (C) 2007-2018 Apple Inc. All rights reserved. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+# Script to tidy up Xcode project.pbxproj files. >+ >+use strict; >+use warnings; >+ >+use English; >+use File::Basename; >+use File::Spec; >+use File::Temp qw(tempfile); >+use Getopt::Long; >+ >+sub findGroupsToConvertToDirectory($$$$); >+sub loadXcodeProjectFile($); >+sub main(); >+sub mapFoldersToDirectories($$); >+sub parseChildrenFromGroup($); >+sub parseFileReference($); >+sub parseXcodeProjectFile($); >+sub saveXcodeProjectFile($); >+sub updateFoldersToDirectories($); >+ >+exit(main()); >+ >+sub main() >+{ >+ my $dryRun = 0; >+ my $forceUpdate = 0; >+ my $mapFolders = 0; >+ my $quiet = 0; >+ my $showHelp; >+ >+ my $getOptionsResult = GetOptions( >+ 'f|force!' => \$forceUpdate, >+ 'h|help' => \$showHelp, >+ 'm|map-folders' => \$mapFolders, >+ 'n|dry-run' => \$dryRun, >+ 'q|quiet' => \$quiet, >+ ); >+ >+ if (scalar(@ARGV) == 0 && !$showHelp) { >+ print STDERR "ERROR: No Xcode project files (project.pbxproj) listed on command-line.\n"; >+ undef $getOptionsResult; >+ } >+ >+ if (!$getOptionsResult || $showHelp) { >+ print STDERR <<__END__; >+Usage: @{[ basename($0) ]} [options] path/to/project.pbxproj [path/to/project.pbxproj ...] >+ -f|--[no-]force force project update even with errors (default: no force) >+ -h|--help show this help message >+ -m|--map-folders map folders in Xcode to directories on disk if they exist >+ -n|--dry-run make changes but don't save them back to the project file >+ -q|--quiet do not output progress messages >+__END__ >+ return 1; >+ } >+ >+ for my $file (@ARGV) { >+ print "Reading project file $file...\n" unless $quiet; >+ my $projectFile = loadXcodeProjectFile($file); >+ >+ if ($mapFolders) { >+ print "Fixing folders that can map to directories...\n" unless $quiet; >+ mapFoldersToDirectories($projectFile, $forceUpdate); >+ updateFoldersToDirectories($projectFile) if !$dryRun; >+ } >+ >+ if (!$dryRun) { >+ print "Saving project file $file...\n" unless $quiet; >+ saveXcodeProjectFile($projectFile); >+ } >+ } >+ print "Done.\n" unless $quiet; >+ >+ return 0; >+} >+ >+sub findGroupsToConvertToDirectory($$$$) >+{ >+ my ($groupID, $parentPath, $projectPath, $projectFile) = @_; >+ my $errorCount = 0; >+ my $files = $projectFile->{files}; >+ my $groups = $projectFile->{groups}; >+ >+ my $groupSourceTree = $groups->{$groupID}{sourceTree}; >+ if ($groupSourceTree eq "<group>" || $groupSourceTree eq "SOURCE_ROOT") { >+ my $directory = File::Spec->catdir($parentPath, $groups->{$groupID}{groupName}); >+ if (-d $directory) { >+ # Mark this group as needing an update to use a path. >+ $groups->{$groupID}{_updateGroupPath} = $directory; >+ >+ # Find children (files and groups) that need an update to use a path. >+ my %children = parseChildrenFromGroup($groups->{$groupID}{text}); >+ for my $childID (keys %children) { >+ if (exists $files->{$childID}) { >+ my ($fileID, $fileName, $unusedName, $path, $sourceTree) = parseFileReference($files->{$childID}{text}); >+ my $expectedPath = File::Spec->catfile($directory, $fileName); >+ my $actualPath; >+ if ($sourceTree eq "SOURCE_ROOT") { >+ $actualPath = File::Spec->catfile($projectPath, $path); >+ } elsif ($sourceTree eq "<group>") { >+ if (exists $groups->{$groupID}{pathValue}) { >+ $actualPath = File::Spec->catfile($directory, $path); >+ } else { >+ $actualPath = File::Spec->catfile($parentPath, $path); >+ } >+ } elsif ($sourceTree eq "BUILT_PRODUCTS_DIR") { >+ next; # Skip these as we can't check if files exist in this directory until after building. >+ } else { >+ die "Unexpected sourceTree \"$sourceTree\" for child $childID"; >+ } >+ if (! -e $expectedPath) { >+ $errorCount++; >+ if (-e $actualPath) { >+ print "MOVE: $actualPath $expectedPath\n"; >+ } else { >+ print "MISSING: $actualPath\n"; >+ } >+ } else { >+ $files->{$childID}{_updatePathWithoutName} = $fileName; >+ } >+ } elsif (exists $groups->{$childID} && $groups->{$groupID}{_updateGroupPath}) { >+ my $groupName = $groups->{$childID}{groupName}; >+ $errorCount += findGroupsToConvertToDirectory($childID, $directory, $projectPath, $projectFile); >+ } >+ } >+ } else { >+ if (exists $groups->{$groupID}{pathValue}) { >+ $parentPath = File::Spec->catdir($parentPath, $groups->{$groupID}{pathValue}); >+ } >+ # Find children that may need an updated path inside folders that don't use a path, >+ # but whose parent folder(s) may have changed to use a path. >+ my %children = parseChildrenFromGroup($groups->{$groupID}{text}); >+ for my $childID (keys %children) { >+ if (exists $files->{$childID}) { >+ my ($fileID, $fileName, $name, $path, $sourceTree) = parseFileReference($files->{$childID}{text}); >+ my $expectedPath; >+ if ($sourceTree eq "SOURCE_ROOT") { >+ $expectedPath = File::Spec->catfile($projectPath, $path); >+ } elsif ($sourceTree eq "<group>") { >+ next if -e File::Spec->catfile($parentPath, $path); # Nothing to do here. >+ my @parentDirs = File::Spec->splitdir($parentPath); >+ my @childPath = File::Spec->splitdir($path); >+ # This works because the updated $parentPath contains one or more directories >+ # that don't need to be in the child's path any longer, so we pop them off >+ # until they no longer match. >+ for (my $i = $#parentDirs; $i >= 0 && $parentDirs[$i] eq $childPath[0]; --$i) { >+ shift @childPath; >+ } >+ my $updatedPath = File::Spec->catfile(@childPath); >+ die "Could not create new path for $fileName ($childID)" if ! -e File::Spec->catfile($parentPath, $updatedPath); >+ if ($fileName eq $updatedPath) { >+ $files->{$childID}{_updatePathWithoutName} = $updatedPath; >+ } else { >+ $files->{$childID}{_updatePathWithName} = $updatedPath; >+ } >+ next; # This will be updated in mapFoldersToDirectories(). >+ } elsif ($sourceTree eq "BUILT_PRODUCTS_DIR") { >+ next; # Skip these as we can't check if files exist in this directory until after building. >+ } elsif ($sourceTree eq "DEVELOPER_DIR") { >+ next; # Skip these as they are usually system frameworks or similar. >+ } elsif ($sourceTree eq "SDKROOT") { >+ next; # Skip these as they are usually system frameworks or similar. >+ } elsif ($sourceTree eq "<absolute>") { >+ next; # Skip these as they are usually system frameworks or similar. >+ } else { >+ die "Unexpected child sourceTree \"$sourceTree\" for $childID"; >+ } >+ if (! -e $expectedPath) { >+ $errorCount++; >+ print "MISSING: $expectedPath\n"; >+ } >+ } elsif (exists $groups->{$childID}) { >+ my $groupName = $groups->{$childID}{groupName}; >+ $errorCount += findGroupsToConvertToDirectory($childID, $parentPath, $projectPath, $projectFile); >+ } >+ } >+ } >+ } elsif ($groupSourceTree eq "BUILT_PRODUCTS_DIR") { >+ # Skip these as we can't check if files exist in this directory until after building. >+ } else { >+ die "Unexpected group sourceTree \"$groupSourceTree\" for $groupID"; >+ } >+ >+ return $errorCount; >+} >+ >+sub loadXcodeProjectFile($) >+{ >+ my ($file) = @_; >+ >+ if (basename($file) =~ /\.xcodeproj$/) { >+ $file = File::Spec->catfile($file, "project.pbxproj"); >+ } >+ >+ if (basename($file) ne "project.pbxproj") { >+ die "FATAL: Not an Xcode project file: $file\n"; >+ } >+ >+ if (! -f $file) { >+ die "FATAL: Xcode project file does not exist: $file\n"; >+ } >+ >+ my $projectFile = { >+ file => $file, >+ }; >+ >+ { >+ local $INPUT_RECORD_SEPARATOR; # Turn on slurp mode. >+ open(IN, "<", $file) || die "Could not open $file: $!"; >+ $projectFile->{contents} = <IN>; >+ close(IN); >+ } >+ >+ parseXcodeProjectFile($projectFile); >+ >+ return $projectFile; >+} >+ >+sub mapFoldersToDirectories($$) >+{ >+ my ($projectFile, $forceUpdate) = @_; >+ >+ # Recursively iterate through children of mainGroup to find groups that map to directories. >+ my $errorCount = 0; >+ my $mainGroupID = $projectFile->{project}{mainGroupID}; >+ my %children = parseChildrenFromGroup($projectFile->{groups}{$mainGroupID}{text}); >+ for my $childID (keys %children) { >+ if (exists $projectFile->{groups}{$childID}) { >+ my $groupName = $projectFile->{groups}{$childID}{groupName}; >+ my $projectDirectory = dirname(dirname($projectFile->{file})); >+ if (exists $projectFile->{groups}{$mainGroupID}{pathValue}) { >+ $projectDirectory = File::Spec->catdir($projectDirectory, $projectFile->{groups}{$mainGroupID}{pathValue}); >+ } >+ $errorCount += findGroupsToConvertToDirectory($childID, $projectDirectory, $projectDirectory, $projectFile); >+ } >+ } >+ >+ die "ERROR: Found $errorCount issues that need to be fixed first" if $errorCount != 0 && !$forceUpdate; >+} >+ >+sub parseChildrenFromGroup($) >+{ >+ my ($text) = @_; >+ my %children; >+ >+ my $parsingChildren = 0; >+ for my $line (split(/^/, $text)) { >+ if ($line =~ m#^\s*children = \($#) { >+ $parsingChildren = 1; >+ next; >+ } >+ if ($parsingChildren && $line =~ m#^\s*([0-9A-F]{24}) /\* (.+) \*/,$#) { >+ $children{$1} = $2; >+ } >+ if ($parsingChildren && $line =~ m#^\s*\);$#) { >+ $parsingChildren = 0; >+ next; >+ } >+ } >+ >+ return %children; >+} >+ >+sub parseFileReference($) >+{ >+ my ($line) = @_; >+ my $fileID; >+ my $fileName; >+ my $name; >+ my $path; >+ my $sourceTree; >+ >+ if ($line =~ m#^\s*([0-9A-F]{24}) /\* (.+) \*/ = {#) { >+ $fileID = $1; >+ $fileName = $2; >+ if ($line =~ m# name = ("?)\Q$fileName\E(\1); #) { >+ $name = $fileName; >+ } >+ if ($line =~ m# path = ("?)(.*\Q$fileName\E)(\1); #) { >+ $path = $2; >+ } >+ if ($line =~ m# sourceTree = ("?)([^;]+)(\1); #) { >+ $sourceTree = $2; >+ } >+ } >+ >+ return ($fileID, $fileName, $name, $path, $sourceTree); >+} >+ >+sub parseXcodeProjectFile($) >+{ >+ my ($projectFile) = @_; >+ >+ open(IN, "<", \$projectFile->{contents}); >+ while (my $line = <IN>) { >+ if ($line eq "/* Begin PBXFileReference section */\n") { >+ do { >+ $line = <IN>; >+ my ($fileID, $fileName, $name, $unusedPath, $unusedSourceTree) = parseFileReference($line); >+ $projectFile->{files}{$fileID}{text} = $line if defined $fileID; >+ } until ($line eq "/* End PBXFileReference section */\n"); >+ } elsif ($line eq "/* Begin PBXGroup section */\n") { >+ do { >+ $line = <IN>; >+ if ($line =~ m#^(\s+)([0-9-A-F]{24})( /\* (.+) \*/)? = {\n$#) { >+ my $groupEnd = "$1};\n"; >+ my $groupID = $2; >+ my $groupName = $4 || "__NO_NAME__"; >+ my $groupText = $line; >+ my $nameValue; >+ my $pathValue; >+ my $sourceTree; >+ do { >+ $line = <IN>; >+ $nameValue = $2 if $line =~ m#^\s*name = ("?)(.*)(\1);$#; >+ $pathValue = $2 if $line =~ m#^\s*path = ("?)(.*)(\1);$#; >+ $sourceTree = $2 if $line =~ m#^\s*sourceTree = ("?)(.*)(\1);#; >+ $groupText .= $line; >+ } until ($line eq $groupEnd); >+ $projectFile->{groups}{$groupID} = +{ >+ groupName => $groupName, >+ sourceTree => $sourceTree, >+ text => $groupText, >+ }; >+ $projectFile->{groups}{$groupID}{nameValue} = $nameValue if defined $nameValue; >+ $projectFile->{groups}{$groupID}{pathValue} = $pathValue if defined $pathValue; >+ } >+ } until ($line eq "/* End PBXGroup section */\n"); >+ } elsif ($line eq "/* Begin PBXProject section */\n") { >+ do { >+ $line = <IN>; >+ $projectFile->{project}{mainGroupID} = $2 if $line =~ m#^(\s*)mainGroup = ([0-9A-F]{24})( /\* .+ \*/)?;$#; >+ $projectFile->{project}{projectDirPath} = $2 if $line =~ m#^(\s*)projectDirPath = "([^"]*)";$#; >+ $projectFile->{project}{projectRoot} = $2 if $line =~ m#^(\s*)projectRoot = "([^"]*)";$#; >+ } until ($line eq "/* End PBXProject section */\n"); >+ } >+ } >+ close(IN); >+} >+ >+sub saveXcodeProjectFile($) >+{ >+ my ($projectFile) = @_; >+ >+ my ($OUT, $tempFileName) = tempfile( >+ basename($projectFile->{file}) . "-XXXXXXXX", >+ DIR => dirname($projectFile->{file}), >+ UNLINK => 0, >+ ); >+ >+ # Clean up temp file in case of die() >+ $SIG{__DIE__} = sub { >+ close(IN); >+ close($OUT); >+ unlink($tempFileName); >+ }; >+ >+ print $OUT $projectFile->{contents}; >+ close($OUT); >+ >+ unlink($projectFile->{file}) || die "Could not delete $projectFile->{file}: $!"; >+ rename($tempFileName, $projectFile->{file}) || die "Could not rename $tempFileName to $projectFile->{file}: $!"; >+} >+ >+sub updateFoldersToDirectories($) >+{ >+ my ($projectFile) = @_; >+ >+ open(IN, "<", \$projectFile->{contents}); >+ my $updatedContents = ""; >+ open(OUT, ">", \$updatedContents); >+ while (my $line = <IN>) { >+ if ($line eq "/* Begin PBXFileReference section */\n") { >+ print OUT $line; >+ do { >+ $line = <IN>; >+ my ($fileID, $fileName, $name, $path, $unusedSourceTree) = parseFileReference($line); >+ if (defined $fileID) { >+ if (exists $projectFile->{files}{$fileID}{_updatePathWithoutName}) { >+ $line =~ s# name = ("?)\Q$fileName\E(\1); # # if defined $name; >+ $line =~ s# path = ("?).*/\Q$fileName\E(\1); # path = $1$fileName$1; #; >+ $line =~ s# sourceTree = ("?).*(\1); # sourceTree = "<group>"; #; >+ } elsif (exists $projectFile->{files}{$fileID}{_updatePathWithName}) { >+ $line =~ s# name = ("?)\Q$fileName\E(\1); # # if defined $name; >+ my $updatedPath = $projectFile->{files}{$fileID}{_updatePathWithName}; >+ $line =~ s# path = ("?).*/\Q$fileName\E(\1); # path = $1$updatedPath$1; #; >+ } >+ } >+ print OUT $line; >+ } until ($line eq "/* End PBXFileReference section */\n"); >+ } elsif ($line eq "/* Begin PBXGroup section */\n") { >+ print OUT $line; >+ do { >+ $line = <IN>; >+ if ($line =~ m#^(\s+)([0-9-A-F]{24})( /\* (.+) \*/)? = {\n$#) { >+ my $groupEnd = "$1};\n"; >+ my $groupID = $2; >+ my $groupName = $4 || "__NO_NAME__"; >+ my $groupText = $line; >+ my $shouldFixPath = exists $projectFile->{groups}{$groupID}{_updateGroupPath}; >+ my $convertedNameToPath = 0; >+ do { >+ $line = <IN>; >+ if ($shouldFixPath) { >+ if ($line =~ s#^(\s*)name = #$1path = #) { >+ $convertedNameToPath = 1; >+ } elsif ($convertedNameToPath && $line =~ m#^\s*path = #) { >+ $line = ""; # Omit line from output. >+ } elsif ($projectFile->{groups}{$groupID}{sourceTree} ne "<group>" && $line =~ m#^(\s*)sourceTree = #) { >+ $line =~ s#^(\s*)sourceTree = .*;$#$1sourceTree = "<group>"\;#; >+ } >+ } >+ $groupText .= $line; >+ } until ($line eq $groupEnd); >+ print OUT $groupText; >+ } else { >+ print OUT $line; >+ } >+ } until ($line eq "/* End PBXGroup section */\n"); >+ } else { >+ print OUT $line; >+ } >+ } >+ close(IN); >+ close(OUT); >+ >+ $projectFile->{contents} = $updatedContents; >+} >diff --git a/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseChildrenFromGroup.pl b/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseChildrenFromGroup.pl >new file mode 100644 >index 0000000000000000000000000000000000000000..2dbbe32e564d1db250e24290060b5cf9acfa29d9 >--- /dev/null >+++ b/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseChildrenFromGroup.pl >@@ -0,0 +1,151 @@ >+#!/usr/bin/env perl >+# >+# Copyright (C) 2018 Apple Inc. All rights reserved. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+use strict; >+use warnings; >+ >+use Test::More; >+use FindBin; >+use lib File::Spec->catdir($FindBin::Bin, ".."); >+use LoadAsModule qw(TidyXcodeProjectFile tidy-Xcode-project-file); >+ >+my @testCaseHashRefs = ( >+ >+{ >+ testName => "WebCore mainGroup", >+ groupText => <<'END', >+ 0867D691FE84028FC02AAC07 /* WebCore */ = { >+ isa = PBXGroup; >+ children = ( >+ 288E82F02035D4ED00B0DCFF /* ServerTimingParser.h */, >+ 288E82EE2035D2BE00B0DCFF /* ServerTimingParser.cpp */, >+ 1C09D04B1E31C32800725F18 /* PAL.xcodeproj */, >+ 65C97AF208EA908800ACD273 /* config.h */, >+ EDEC98020AED7E170059137F /* WebCorePrefix.h */, >+ 530A63461FA3E33D0026A545 /* Sources.txt */, >+ 530A63421FA3E33B0026A545 /* SourcesCocoa.txt */, >+ 9307061309E0CA8200B17FE4 /* DerivedSources.make */, >+ 93F19B1908245E59001E9ABC /* Info.plist */, >+ 971145FE14EF006E00674FD9 /* Modules */, >+ 29A812040FBB9B4100510293 /* accessibility */, >+ 71025EC11F99F096004A250C /* animation */, >+ BC1A3790097C6F970019F3D8 /* bindings */, >+ 1A569CC40D7E2B60007C3983 /* bridge */, >+ 26F0C8901A2D79CB002794F8 /* contentextensions */, >+ E1FF8F5B1807362B00132674 /* crypto */, >+ F523D18402DE42E8018635CA /* css */, >+ 26B9998D1803ADFA00D01121 /* cssjit */, >+ F523D32402DE4478018635CA /* dom */, >+ E3AFA9631DA6E8AF002861BD /* domjit */, >+ 93309D86099E64910056E581 /* editing */, >+ 976D6C57122B8A18001FD1F7 /* fileapi */, >+ 51741D080B07257000ED442C /* history */, >+ 93EEC1EC09C2877700C515D1 /* html */, >+ 1C81B94D0E9732D900266E07 /* inspector */, >+ 115CFA66208AF720001E6991 /* layout */, >+ BCB16BFB0979C38700467741 /* loader */, >+ FABE72EC1059C1EB00D999DD /* mathml */, >+ 65BF02180974806300C43196 /* page */, >+ BCF1A5BA097832090061A123 /* platform */, >+ 5DCF83690D59157800953BC6 /* plugins */, >+ F523D2F302DE443B018635CA /* rendering */, >+ 99E45A1318A021760026D88F /* replay */, >+ 1AE82EC90CAAE177002237AE /* storage */, >+ E4763D4A17B2704900D35206 /* style */, >+ B22277CA0D00BF1E0071B782 /* svg */, >+ 417DA4CD13734204007C57FB /* testing */, >+ 2E4346310F546A6800B0F1BA /* workers */, >+ E1F0424309839389006694EA /* xml */, >+ 656580EC09D12B20000E61D7 /* Derived Sources */, >+ 089C1665FE841158C02AAC07 /* Resources */, >+ 3717D7E417ECC36C003C276D /* Scripts */, >+ 0867D69AFE84028FC02AAC07 /* Frameworks */, >+ 034768DFFF38A50411DB9C8B /* Products */, >+ 1CDD44660BA9C80000F90147 /* Configurations */, >+ ); >+ name = WebCore; >+ sourceTree = "<group>"; >+ }; >+END >+ expectedResults => { >+ '288E82F02035D4ED00B0DCFF' => 'ServerTimingParser.h', >+ '288E82EE2035D2BE00B0DCFF' => 'ServerTimingParser.cpp', >+ '1C09D04B1E31C32800725F18' => 'PAL.xcodeproj', >+ '65C97AF208EA908800ACD273' => 'config.h', >+ 'EDEC98020AED7E170059137F' => 'WebCorePrefix.h', >+ '530A63461FA3E33D0026A545' => 'Sources.txt', >+ '530A63421FA3E33B0026A545' => 'SourcesCocoa.txt', >+ '9307061309E0CA8200B17FE4' => 'DerivedSources.make', >+ '93F19B1908245E59001E9ABC' => 'Info.plist', >+ '971145FE14EF006E00674FD9' => 'Modules', >+ '29A812040FBB9B4100510293' => 'accessibility', >+ '71025EC11F99F096004A250C' => 'animation', >+ 'BC1A3790097C6F970019F3D8' => 'bindings', >+ '1A569CC40D7E2B60007C3983' => 'bridge', >+ '26F0C8901A2D79CB002794F8' => 'contentextensions', >+ 'E1FF8F5B1807362B00132674' => 'crypto', >+ 'F523D18402DE42E8018635CA' => 'css', >+ '26B9998D1803ADFA00D01121' => 'cssjit', >+ 'F523D32402DE4478018635CA' => 'dom', >+ 'E3AFA9631DA6E8AF002861BD' => 'domjit', >+ '93309D86099E64910056E581' => 'editing', >+ '976D6C57122B8A18001FD1F7' => 'fileapi', >+ '51741D080B07257000ED442C' => 'history', >+ '93EEC1EC09C2877700C515D1' => 'html', >+ '1C81B94D0E9732D900266E07' => 'inspector', >+ '115CFA66208AF720001E6991' => 'layout', >+ 'BCB16BFB0979C38700467741' => 'loader', >+ 'FABE72EC1059C1EB00D999DD' => 'mathml', >+ '65BF02180974806300C43196' => 'page', >+ 'BCF1A5BA097832090061A123' => 'platform', >+ '5DCF83690D59157800953BC6' => 'plugins', >+ 'F523D2F302DE443B018635CA' => 'rendering', >+ '99E45A1318A021760026D88F' => 'replay', >+ '1AE82EC90CAAE177002237AE' => 'storage', >+ 'E4763D4A17B2704900D35206' => 'style', >+ 'B22277CA0D00BF1E0071B782' => 'svg', >+ '417DA4CD13734204007C57FB' => 'testing', >+ '2E4346310F546A6800B0F1BA' => 'workers', >+ 'E1F0424309839389006694EA' => 'xml', >+ '656580EC09D12B20000E61D7' => 'Derived Sources', >+ '089C1665FE841158C02AAC07' => 'Resources', >+ '3717D7E417ECC36C003C276D' => 'Scripts', >+ '0867D69AFE84028FC02AAC07' => 'Frameworks', >+ '034768DFFF38A50411DB9C8B' => 'Products', >+ '1CDD44660BA9C80000F90147' => 'Configurations', >+ }, >+}, >+ >+); >+ >+my $testCasesCount = scalar @testCaseHashRefs; >+plan(tests => 1 * $testCasesCount); # Total number of assertions. >+ >+foreach my $testCase (@testCaseHashRefs) { >+ my $expectedResults = $testCase->{expectedResults}; >+ >+ my $testNameStart = "parseChildrenFromGroup(): $testCase->{testName}"; >+ my %actualResults = TidyXcodeProjectFile::parseChildrenFromGroup($testCase->{groupText}); >+ is_deeply(\%actualResults, $expectedResults, $testNameStart); >+} >diff --git a/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseFileReference.pl b/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseFileReference.pl >new file mode 100644 >index 0000000000000000000000000000000000000000..c38da9df49ac1925c374bd25337d35bd4401cc96 >--- /dev/null >+++ b/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseFileReference.pl >@@ -0,0 +1,130 @@ >+#!/usr/bin/env perl >+# >+# Copyright (C) 2018 Apple Inc. All rights reserved. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+use strict; >+use warnings; >+ >+use Test::More; >+use FindBin; >+use lib File::Spec->catdir($FindBin::Bin, ".."); >+use LoadAsModule qw(TidyXcodeProjectFile tidy-Xcode-project-file); >+ >+my @testCaseHashRefs = ( >+ >+{ >+ testName => "AudioTrackPrivateMediaStream.h", >+ fileText => <<'END', >+ 07D6A4F61BF2307D00174146 /* AudioTrackPrivateMediaStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioTrackPrivateMediaStream.h; path = platform/mediastream/AudioTrackPrivateMediaStream.h; sourceTree = SOURCE_ROOT; }; >+END >+ expectedResults => +[ >+ '07D6A4F61BF2307D00174146', >+ 'AudioTrackPrivateMediaStream.h', >+ 'AudioTrackPrivateMediaStream.h', >+ 'platform/mediastream/AudioTrackPrivateMediaStream.h', >+ 'SOURCE_ROOT', >+ ], >+}, >+ >+{ >+ testName => "IDLParser.pm", >+ fileText => <<'END', >+ 14813BF309EDF88E00F757E1 /* IDLParser.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = IDLParser.pm; path = scripts/IDLParser.pm; sourceTree = "<group>"; }; >+END >+ expectedResults => +[ >+ '14813BF309EDF88E00F757E1', >+ 'IDLParser.pm', >+ 'IDLParser.pm', >+ 'scripts/IDLParser.pm', >+ '<group>', >+ ], >+}, >+ >+{ >+ testName => "extract-localizable-strings.pl", >+ fileText => <<'END', >+ 3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; name = extract-localizable-strings.pl; path = "Scripts/extract-localizable-strings.pl"; sourceTree = "<group>"; }; >+END >+ expectedResults => +[ >+ '3717D7E517ECC3A6003C276D', >+ 'extract-localizable-strings.pl', >+ 'extract-localizable-strings.pl', >+ 'Scripts/extract-localizable-strings.pl', >+ '<group>', >+ ], >+}, >+ >+{ >+ testName => "generate-bindings.pl", >+ fileText => <<'END', >+ 93F8B3070A300FEA00F61AB8 /* generate-bindings.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = "generate-bindings.pl"; path = "scripts/generate-bindings.pl"; sourceTree = "<group>"; }; >+END >+ expectedResults => +[ >+ '93F8B3070A300FEA00F61AB8', >+ 'generate-bindings.pl', >+ 'generate-bindings.pl', >+ 'scripts/generate-bindings.pl', >+ '<group>', >+ ], >+}, >+ >+{ >+ testName => "RadioButtonGroups.h", >+ fileText => <<'END', >+ 93F925410F7EF5B8007E37C9 /* RadioButtonGroups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RadioButtonGroups.h; sourceTree = "<group>"; }; >+END >+ expectedResults => +[ >+ '93F925410F7EF5B8007E37C9', >+ 'RadioButtonGroups.h', >+ undef, >+ 'RadioButtonGroups.h', >+ '<group>', >+ ], >+}, >+ >+{ >+ testName => "Info.plist", >+ fileText => <<'END', >+ 939811320824BF01008DF038 /* Info.plist */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = mac/Info.plist; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 1; }; >+END >+ expectedResults => +[ >+ '939811320824BF01008DF038', >+ 'Info.plist', >+ 'Info.plist', >+ 'mac/Info.plist', >+ 'SOURCE_ROOT', >+ ], >+}, >+ >+); >+ >+my $testCasesCount = scalar @testCaseHashRefs; >+plan(tests => 1 * $testCasesCount); # Total number of assertions. >+ >+foreach my $testCase (@testCaseHashRefs) { >+ my $expectedResults = $testCase->{expectedResults}; >+ >+ my $testNameStart = "parseFileReference(): $testCase->{testName}"; >+ my @actualResults = TidyXcodeProjectFile::parseFileReference($testCase->{fileText}); >+ is_deeply(\@actualResults, $expectedResults, $testNameStart); >+} >diff --git a/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseXcodeProjectFile.pl b/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseXcodeProjectFile.pl >new file mode 100644 >index 0000000000000000000000000000000000000000..e876fed5266046c3a49b4691ca128e934542f153 >--- /dev/null >+++ b/Tools/Scripts/webkitperl/tidy-Xcode-project-file_unittest/parseXcodeProjectFile.pl >@@ -0,0 +1,230 @@ >+#!/usr/bin/env perl >+# >+# Copyright (C) 2018 Apple Inc. All rights reserved. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+use strict; >+use warnings; >+ >+use Test::More; >+use FindBin; >+use lib File::Spec->catdir($FindBin::Bin, ".."); >+use LoadAsModule qw(TidyXcodeProjectFile tidy-Xcode-project-file); >+ >+my @testCaseHashRefs = ( >+ >+{ >+ testName => "Source/WebCore/WebCore.xcodeproj/project.pbxproj", >+ projectFile => { >+ contents => <<'END', >+// !$*UTF8*$! >+{ >+ archiveVersion = 1; >+ classes = { >+ }; >+ objectVersion = 46; >+ objects = { >+ >+/* Begin PBXAggregateTarget section */ >+/* End PBXAggregateTarget section */ >+ >+/* Begin PBXBuildFile section */ >+/* End PBXBuildFile section */ >+ >+/* Begin PBXContainerItemProxy section */ >+/* End PBXContainerItemProxy section */ >+ >+/* Begin PBXCopyFilesBuildPhase section */ >+/* End PBXCopyFilesBuildPhase section */ >+ >+/* Begin PBXFileReference section */ >+ 9920398018B95BC600B39AF9 /* UserInputBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserInputBridge.cpp; sourceTree = "<group>"; }; >+ 9920398118B95BC600B39AF9 /* UserInputBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInputBridge.h; sourceTree = "<group>"; }; >+/* End PBXFileReference section */ >+ >+/* Begin PBXFrameworksBuildPhase section */ >+/* End PBXFrameworksBuildPhase section */ >+ >+/* Begin PBXGroup section */ >+ 0867D691FE84028FC02AAC07 /* WebCore */ = { >+ isa = PBXGroup; >+ children = ( >+ 99E45A1318A021760026D88F /* replay */, >+ ); >+ name = WebCore; >+ sourceTree = "<group>"; >+ }; >+ 99E45A1318A021760026D88F /* replay */ = { >+ isa = PBXGroup; >+ children = ( >+ 9920398018B95BC600B39AF9 /* UserInputBridge.cpp */, >+ 9920398118B95BC600B39AF9 /* UserInputBridge.h */, >+ ); >+ path = replay; >+ sourceTree = "<group>"; >+ }; >+/* End PBXGroup section */ >+ >+/* Begin PBXHeadersBuildPhase section */ >+/* End PBXHeadersBuildPhase section */ >+ >+/* Begin PBXNativeTarget section */ >+/* End PBXNativeTarget section */ >+ >+/* Begin PBXProject section */ >+ 0867D690FE84028FC02AAC07 /* Project object */ = { >+ isa = PBXProject; >+ attributes = { >+ BuildIndependentTargetsInParallel = YES; >+ LastSwiftUpdateCheck = 0700; >+ LastUpgradeCheck = 0700; >+ }; >+ buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */; >+ compatibilityVersion = "Xcode 3.2"; >+ developmentRegion = English; >+ hasScannedForEncodings = 1; >+ knownRegions = ( >+ English, >+ Japanese, >+ French, >+ German, >+ Spanish, >+ Dutch, >+ Italian, >+ ); >+ mainGroup = 0867D691FE84028FC02AAC07 /* WebCore */; >+ productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; >+ projectDirPath = ""; >+ projectReferences = ( >+ { >+ ProductGroup = 1C09D04C1E31C32800725F18 /* Products */; >+ ProjectRef = 1C09D04B1E31C32800725F18 /* PAL.xcodeproj */; >+ }, >+ ); >+ projectRoot = ""; >+ targets = ( >+ 41816F7913859C550057AAA4 /* All */, >+ 93F198A508245E59001E9ABC /* WebCore */, >+ 5355E8D11F967E9D0031E08C /* Generate Unified Sources */, >+ DD041FBE09D9DDBE0010AF2A /* Derived Sources */, >+ 417DA6CF13734E02007C57FB /* WebCoreTestSupport */, >+ E1BA66F31742BDE000C20251 /* WebCoreTestShim */, >+ ); >+ }; >+/* End PBXProject section */ >+ >+/* Begin PBXReferenceProxy section */ >+/* End PBXReferenceProxy section */ >+ >+/* Begin PBXResourcesBuildPhase section */ >+/* End PBXResourcesBuildPhase section */ >+ >+/* Begin PBXShellScriptBuildPhase section */ >+/* End PBXShellScriptBuildPhase section */ >+ >+/* Begin PBXSourcesBuildPhase section */ >+/* End PBXSourcesBuildPhase section */ >+ >+/* Begin PBXTargetDependency section */ >+/* End PBXTargetDependency section */ >+ >+/* Begin PBXVariantGroup section */ >+/* End PBXVariantGroup section */ >+ >+/* Begin XCBuildConfiguration section */ >+/* End XCBuildConfiguration section */ >+ >+/* Begin XCConfigurationList section */ >+/* End XCConfigurationList section */ >+ }; >+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */; >+} >+END >+ }, >+ expectedResults => { >+ files => { >+ '9920398018B95BC600B39AF9' => { >+ text => <<'END', >+ 9920398018B95BC600B39AF9 /* UserInputBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserInputBridge.cpp; sourceTree = "<group>"; }; >+END >+ }, >+ '9920398118B95BC600B39AF9' => { >+ text => <<'END', >+ 9920398118B95BC600B39AF9 /* UserInputBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserInputBridge.h; sourceTree = "<group>"; }; >+END >+ }, >+ }, >+ groups => { >+ '0867D691FE84028FC02AAC07' => { >+ groupName => "WebCore", >+ nameValue => "WebCore", >+ sourceTree => "<group>", >+ text => <<'END', >+ 0867D691FE84028FC02AAC07 /* WebCore */ = { >+ isa = PBXGroup; >+ children = ( >+ 99E45A1318A021760026D88F /* replay */, >+ ); >+ name = WebCore; >+ sourceTree = "<group>"; >+ }; >+END >+ }, >+ '99E45A1318A021760026D88F' => { >+ groupName => "replay", >+ pathValue => "replay", >+ sourceTree => "<group>", >+ text => <<'END', >+ 99E45A1318A021760026D88F /* replay */ = { >+ isa = PBXGroup; >+ children = ( >+ 9920398018B95BC600B39AF9 /* UserInputBridge.cpp */, >+ 9920398118B95BC600B39AF9 /* UserInputBridge.h */, >+ ); >+ path = replay; >+ sourceTree = "<group>"; >+ }; >+END >+ }, >+ }, >+ project => { >+ mainGroupID => "0867D691FE84028FC02AAC07", >+ projectDirPath => "", >+ projectRoot => "", >+ }, >+ }, >+}, >+ >+); >+ >+my $testCasesCount = scalar @testCaseHashRefs; >+plan(tests => 1 * $testCasesCount); # Total number of assertions. >+ >+foreach my $testCase (@testCaseHashRefs) { >+ my $expectedResults = $testCase->{expectedResults}; >+ $expectedResults->{contents} = $testCase->{projectFile}->{contents}; >+ >+ my $testNameStart = "parseXcodeProjectFile(): $testCase->{testName}"; >+ my $actualResults = $testCase->{projectFile}; >+ TidyXcodeProjectFile::parseXcodeProjectFile($actualResults); >+ is_deeply($actualResults, $expectedResults, $testNameStart); >+} >diff --git a/Tools/Scripts/webkitpy/style/checker.py b/Tools/Scripts/webkitpy/style/checker.py >index a5908e6016a21ca76b6b2ae3e5419ea9e1ffd7ca..69ba05081eed472305dfc4b45cb6f14f55387d35 100644 >--- a/Tools/Scripts/webkitpy/style/checker.py >+++ b/Tools/Scripts/webkitpy/style/checker.py >@@ -261,6 +261,10 @@ _PATH_RULES_SPECIFIER = [ > os.path.join('Source', 'ThirdParty', 'libwebrtc', 'Source', 'webrtc'), > os.path.join('Source', 'WebCore', 'PAL', 'pal', 'spi')], > ["-readability/naming/underscores"]), >+ >+ ([ # tidy-Xcode-project-file tests use tabs because Xcode project files use tabs. >+ os.path.join('Tools', 'Scripts', 'webkitperl', 'tidy-Xcode-project-file_unittest')], >+ ["-whitespace/tab"]), > ] > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188754
:
348331
|
348344
|
348345
|
468044