1# This file is part of the LibreOffice project. 2# 3# This Source Code Form is subject to the terms of the Mozilla Public 4# License, v. 2.0. If a copy of the MPL was not distributed with this 5# file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7package ClangFormat; 8 9use strict; 10use warnings; 11 12our @EXPORT_OK = qw(get_blacklist set_blacklist get_wanted_version get_own_directory get_extension_regex find check_style); 13 14# Reads the blacklist. 15sub get_blacklist() 16{ 17 my $src = "c|cpp|cxx|h|hxx|inl"; 18 my %blacklist_names = (); 19 20 # Read the blacklist. 21 if (open(LINES, "solenv/clang-format/blacklist")) 22 { 23 while (my $line = <LINES>) 24 { 25 chomp $line; 26 $blacklist_names{$line} = 1; 27 } 28 } 29 30 return \%blacklist_names; 31} 32 33# Writes the blacklist. 34# The single argument is a reference to an array. 35sub set_blacklist 36{ 37 my @filenames = @{$_[0]}; 38 open my $fh, ">", "solenv/clang-format/blacklist" or die $!; 39 print $fh "$_\n" for @filenames; 40 close $fh; 41} 42 43# Returns the clang-format version used of style enforcement. 44sub get_wanted_version() 45{ 46 return "5.0.0"; 47} 48 49# Returns the directory that can host a binary which is used automatically, even 50# if it's not in PATH. 51sub get_own_directory() 52{ 53 return "/opt/lo/bin"; 54} 55 56# Returns a regex matching filenames we clang-format. 57sub get_extension_regex() 58{ 59 return "c|cpp|cxx|h|hxx|inl"; 60} 61 62# Use clang-format from CLANG_FORMAT, from our dedicated directory or from 63# PATH, in this order. 64sub find() 65{ 66 my $version = get_wanted_version(); 67 my $opt_lo = get_own_directory(); 68 my $clang_format; 69 if (!(defined($ENV{CLANG_FORMAT}) && is_matching_clang_format_version($ENV{CLANG_FORMAT}, $version))) 70 { 71 my @dirs = split /:/, $ENV{PATH}; 72 unshift(@dirs, $opt_lo); 73 74 foreach my $dir (@dirs) 75 { 76 if (is_matching_clang_format_version("$dir/clang-format", $version)) 77 { 78 $clang_format = "$dir/clang-format"; 79 last; 80 } 81 } 82 } 83 else 84 { 85 $clang_format = $ENV{CLANG_FORMAT}; 86 } 87 88 if ($^O eq "cygwin" && defined($clang_format)) 89 { 90 $clang_format = `cygpath -m '$clang_format'`; 91 chomp $clang_format; 92 } 93 94 return $clang_format; 95} 96 97# Diffs the original and the formatted version of a single file from the index. 98sub check_style($$) 99{ 100 # Make sure that not staged changes are not considered when diffing. 101 my ($clang_format, $filename) = @_; 102 my $index = $filename . ".index"; 103 system("git show :$filename > $index"); 104 my $format = $index . ".format"; 105 system("'$clang_format' -assume-filename=$filename $index > $format"); 106 my $ret = system("git --no-pager diff --no-index --exit-code $index $format") == 0; 107 unlink($index); 108 unlink($format); 109 return $ret; 110} 111 112# Private functions. 113 114# Is this binary the version we standardize on? 115sub is_matching_clang_format_version($$) 116{ 117 my ($clang_format, $version) = @_; 118 if (! -x $clang_format) 119 { 120 return 0; 121 } 122 123 return `'$clang_format' -version` =~ /^clang-format version $version(-\d+)? \(tags/; 124} 125 1261; 127 128# vim: set shiftwidth=4 softtabstop=4 expandtab: 129