Skip to content

Commit

Permalink
Merge branch 'js/userdiff-cc'
Browse files Browse the repository at this point in the history
Improves the pattern to match the hunk-header for C/C++.

* js/userdiff-cc:
  userdiff: have 'cpp' hunk header pattern catch more C++ anchor points
  t4018: test cases showing that the cpp pattern misses many anchor points
  t4018: test cases for the built-in cpp pattern
  t4018: reduce test files for pattern compilation tests
  t4018: convert custom pattern test to the new infrastructure
  t4018: convert java pattern test to the new infrastructure
  t4018: convert perl pattern tests to the new infrastructure
  t4018: an infrastructure to test hunk headers
  userdiff: support unsigned and long long suffixes of integer constants
  userdiff: support C++ ->* and .* operators in the word regexp
  • Loading branch information
Junio C Hamano committed Mar 31, 2014
2 parents e164a8f + 8a2e8da commit c228a5c
Show file tree
Hide file tree
Showing 33 changed files with 303 additions and 160 deletions.
230 changes: 77 additions & 153 deletions t/t4018-diff-funcname.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,179 +7,103 @@ test_description='Test custom diff function name patterns'

. ./test-lib.sh

LF='
'
cat >Beer.java <<\EOF
public class Beer
{
int special;
public static void main(String args[])
{
String s=" ";
for(int x = 99; x > 0; x--)
{
System.out.print(x + " bottles of beer on the wall "
+ x + " bottles of beer\n"
+ "Take one down, pass it around, " + (x - 1)
+ " bottles of beer on the wall.\n");
}
System.out.print("Go to the store, buy some more,\n"
+ "99 bottles of beer on the wall.\n");
}
}
EOF
sed 's/beer\\/beer,\\/' <Beer.java >Beer-correct.java
cat >Beer.perl <<\EOT
package Beer;
use strict;
use warnings;
use parent qw(Exporter);
our @EXPORT_OK = qw(round finalround);
sub other; # forward declaration
# hello
sub round {
my ($n) = @_;
print "$n bottles of beer on the wall ";
print "$n bottles of beer\n";
print "Take one down, pass it around, ";
$n = $n - 1;
print "$n bottles of beer on the wall.\n";
}
sub finalround
{
print "Go to the store, buy some more\n";
print "99 bottles of beer on the wall.\n");
}
sub withheredocument {
print <<"EOF"
decoy here-doc
EOF
# some lines of context
# to pad it out
print "hello\n";
}
__END__
=head1 NAME
Beer - subroutine to output fragment of a drinking song
=head1 SYNOPSIS
use Beer qw(round finalround);
sub song {
for (my $i = 99; $i > 0; $i--) {
round $i;
}
finalround;
}
test_expect_success 'setup' '
# a non-trivial custom pattern
git config diff.custom1.funcname "!static
!String
[^ ].*s.*" &&
song;
# a custom pattern which matches to end of line
git config diff.custom2.funcname "......Beer\$" &&
=cut
EOT
sed -e '
s/hello/goodbye/
s/beer\\/beer,\\/
s/more\\/more,\\/
s/song;/song();/
' <Beer.perl >Beer-correct.perl
# alternation in pattern
git config diff.custom3.funcname "Beer$" &&
git config diff.custom3.xfuncname "^[ ]*((public|static).*)$" &&
test_expect_funcname () {
lang=${2-java}
test_expect_code 1 git diff --no-index -U1 \
"Beer.$lang" "Beer-correct.$lang" >diff &&
grep "^@@.*@@ $1" diff
}
# for regexp compilation tests
echo A >A.java &&
echo B >B.java
'

for p in ada bibtex cpp csharp fortran html java matlab objc pascal perl php python ruby tex
diffpatterns="
ada
bibtex
cpp
csharp
fortran
html
java
matlab
objc
pascal
perl
php
python
ruby
tex
custom1
custom2
custom3
"

for p in $diffpatterns
do
test_expect_success "builtin $p pattern compiles" '
echo "*.java diff=$p" >.gitattributes &&
test_expect_code 1 git diff --no-index \
Beer.java Beer-correct.java 2>msg &&
! grep fatal msg &&
! grep error msg
A.java B.java 2>msg &&
! test_i18ngrep fatal msg &&
! test_i18ngrep error msg
'
test_expect_success "builtin $p wordRegex pattern compiles" '
echo "*.java diff=$p" >.gitattributes &&
test_expect_code 1 git diff --no-index --word-diff \
Beer.java Beer-correct.java 2>msg &&
! grep fatal msg &&
! grep error msg
A.java B.java 2>msg &&
! test_i18ngrep fatal msg &&
! test_i18ngrep error msg
'
done

test_expect_success 'default behaviour' '
rm -f .gitattributes &&
test_expect_funcname "public class Beer\$"
'

test_expect_success 'set up .gitattributes declaring drivers to test' '
cat >.gitattributes <<-\EOF
*.java diff=java
*.perl diff=perl
EOF
'

test_expect_success 'preset java pattern' '
test_expect_funcname "public static void main("
'

test_expect_success 'preset perl pattern' '
test_expect_funcname "sub round {\$" perl
'

test_expect_success 'perl pattern accepts K&R style brace placement, too' '
test_expect_funcname "sub finalround\$" perl
'

test_expect_success 'but is not distracted by end of <<here document' '
test_expect_funcname "sub withheredocument {\$" perl
'

test_expect_success 'perl pattern is not distracted by sub within POD' '
test_expect_funcname "=head" perl
'

test_expect_success 'perl pattern gets full line of POD header' '
test_expect_funcname "=head1 SYNOPSIS\$" perl
'

test_expect_success 'perl pattern is not distracted by forward declaration' '
test_expect_funcname "package Beer;\$" perl
'

test_expect_success 'custom pattern' '
test_config diff.java.funcname "!static
!String
[^ ].*s.*" &&
test_expect_funcname "int special;\$"
'

test_expect_success 'last regexp must not be negated' '
echo "*.java diff=java" >.gitattributes &&
test_config diff.java.funcname "!static" &&
test_expect_code 128 git diff --no-index Beer.java Beer-correct.java 2>msg &&
grep ": Last expression must not be negated:" msg
test_expect_code 128 git diff --no-index A.java B.java 2>msg &&
test_i18ngrep ": Last expression must not be negated:" msg
'

test_expect_success 'pattern which matches to end of line' '
test_config diff.java.funcname "Beer\$" &&
test_expect_funcname "Beer\$"
test_expect_success 'setup hunk header tests' '
for i in $diffpatterns
do
echo "$i-* diff=$i"
done > .gitattributes &&
# add all test files to the index
(
cd "$TEST_DIRECTORY"/t4018 &&
git --git-dir="$TRASH_DIRECTORY/.git" add .
) &&
# place modified files in the worktree
for i in $(git ls-files)
do
sed -e "s/ChangeMe/IWasChanged/" <"$TEST_DIRECTORY/t4018/$i" >"$i" || return 1
done
'

test_expect_success 'alternation in pattern' '
test_config diff.java.funcname "Beer$" &&
test_config diff.java.xfuncname "^[ ]*((public|static).*)$" &&
test_expect_funcname "public static void main("
'
# check each individual file
for i in $(git ls-files)
do
if grep broken "$i" >/dev/null 2>&1
then
result=failure
else
result=success
fi
test_expect_$result "hunk header: $i" "
test_when_finished 'cat actual' && # for debugging only
git diff -U1 $i >actual &&
grep '@@ .* @@.*RIGHT' actual
"
done

test_done
18 changes: 18 additions & 0 deletions t/t4018/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
How to write RIGHT test cases
=============================

Insert the word "ChangeMe" (exactly this form) at a distance of
at least two lines from the line that must appear in the hunk header.

The text that must appear in the hunk header must contain the word
"right", but in all upper-case, like in the title above.

To mark a test case that highlights a malfunction, insert the word
BROKEN in all lower-case somewhere in the file.

This text is a bit twisted and out of order, but it is itself a
test case for the default hunk header pattern. Know what you are doing
if you change it.

BTW, this tests that the head line goes to the hunk header, not the line
of equal signs.
4 changes: 4 additions & 0 deletions t/t4018/cpp-c++-function
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Item RIGHT::DoSomething( Args with_spaces )
{
ChangeMe;
}
4 changes: 4 additions & 0 deletions t/t4018/cpp-class-constructor
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Item::Item(int RIGHT)
{
ChangeMe;
}
5 changes: 5 additions & 0 deletions t/t4018/cpp-class-constructor-mem-init
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Item::Item(int RIGHT) :
member(0)
{
ChangeMe;
}
4 changes: 4 additions & 0 deletions t/t4018/cpp-class-definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class RIGHT
{
int ChangeMe;
};
5 changes: 5 additions & 0 deletions t/t4018/cpp-class-definition-derived
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class RIGHT :
public Baseclass
{
int ChangeMe;
};
4 changes: 4 additions & 0 deletions t/t4018/cpp-class-destructor
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
RIGHT::~RIGHT()
{
ChangeMe;
}
4 changes: 4 additions & 0 deletions t/t4018/cpp-function-returning-global-type
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
::Item get::it::RIGHT()
{
ChangeMe;
}
5 changes: 5 additions & 0 deletions t/t4018/cpp-function-returning-nested
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
get::Item get::it::RIGHT()
{
ChangeMe;
}

4 changes: 4 additions & 0 deletions t/t4018/cpp-function-returning-pointer
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const char *get_it_RIGHT(char *ptr)
{
ChangeMe;
}
4 changes: 4 additions & 0 deletions t/t4018/cpp-function-returning-reference
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
string& get::it::RIGHT(char *ptr)
{
ChangeMe;
}
5 changes: 5 additions & 0 deletions t/t4018/cpp-gnu-style-function
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const char *
RIGHT(int arg)
{
ChangeMe;
}
4 changes: 4 additions & 0 deletions t/t4018/cpp-namespace-definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace RIGHT
{
ChangeMe;
}
4 changes: 4 additions & 0 deletions t/t4018/cpp-operator-definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Value operator+(Value LEFT, Value RIGHT)
{
ChangeMe;
}
8 changes: 8 additions & 0 deletions t/t4018/cpp-skip-access-specifiers
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class RIGHT : public Baseclass
{
public:
protected:
private:
void DoSomething();
int ChangeMe;
};
9 changes: 9 additions & 0 deletions t/t4018/cpp-skip-comment-block
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
struct item RIGHT(int i)
// Do not
// pick up
/* these
** comments.
*/
{
ChangeMe;
}
8 changes: 8 additions & 0 deletions t/t4018/cpp-skip-labels
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
void RIGHT (void)
{
repeat: // C++ comment
next: /* C comment */
do_something();

ChangeMe;
}
9 changes: 9 additions & 0 deletions t/t4018/cpp-struct-definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
struct RIGHT {
unsigned
/* this bit field looks like a label and should not be picked up */
decoy_bitfield: 2,
more : 1;
int filler;

int ChangeMe;
};
7 changes: 7 additions & 0 deletions t/t4018/cpp-struct-single-line
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
void wrong()
{
}

struct RIGHT_iterator_tag {};

int ChangeMe;
4 changes: 4 additions & 0 deletions t/t4018/cpp-template-function-definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
template<class T> int RIGHT(T arg)
{
ChangeMe;
}
Loading

0 comments on commit c228a5c

Please sign in to comment.