Merge branch 'rs/include-comments-before-the-function-header'
"git grep -W", "git diff -W" and their friends learned a heuristic to extend a pre-context beyond the line that matches the "function pattern" (aka "diff.*.xfuncname") to include a comment block, if exists, that immediately precedes it. * rs/include-comments-before-the-function-header: grep: show non-empty lines before functions with -W grep: update boundary variable for pre-context t7810: improve check of -W with user-defined function lines xdiff: show non-empty lines before functions with -W xdiff: factor out is_func_rec() t4051: add test for comments preceding function lines
This commit is contained in:
commit
f034901648
35
grep.c
35
grep.c
@ -1476,31 +1476,52 @@ static void show_funcname_line(struct grep_opt *opt, struct grep_source *gs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_empty_line(const char *bol, const char *eol);
|
||||||
|
|
||||||
static void show_pre_context(struct grep_opt *opt, struct grep_source *gs,
|
static void show_pre_context(struct grep_opt *opt, struct grep_source *gs,
|
||||||
char *bol, char *end, unsigned lno)
|
char *bol, char *end, unsigned lno)
|
||||||
{
|
{
|
||||||
unsigned cur = lno, from = 1, funcname_lno = 0;
|
unsigned cur = lno, from = 1, funcname_lno = 0, orig_from;
|
||||||
int funcname_needed = !!opt->funcname;
|
int funcname_needed = !!opt->funcname, comment_needed = 0;
|
||||||
|
|
||||||
if (opt->funcbody && !match_funcname(opt, gs, bol, end))
|
|
||||||
funcname_needed = 2;
|
|
||||||
|
|
||||||
if (opt->pre_context < lno)
|
if (opt->pre_context < lno)
|
||||||
from = lno - opt->pre_context;
|
from = lno - opt->pre_context;
|
||||||
if (from <= opt->last_shown)
|
if (from <= opt->last_shown)
|
||||||
from = opt->last_shown + 1;
|
from = opt->last_shown + 1;
|
||||||
|
orig_from = from;
|
||||||
|
if (opt->funcbody) {
|
||||||
|
if (match_funcname(opt, gs, bol, end))
|
||||||
|
comment_needed = 1;
|
||||||
|
else
|
||||||
|
funcname_needed = 1;
|
||||||
|
from = opt->last_shown + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Rewind. */
|
/* Rewind. */
|
||||||
while (bol > gs->buf &&
|
while (bol > gs->buf && cur > from) {
|
||||||
cur > (funcname_needed == 2 ? opt->last_shown + 1 : from)) {
|
char *next_bol = bol;
|
||||||
char *eol = --bol;
|
char *eol = --bol;
|
||||||
|
|
||||||
while (bol > gs->buf && bol[-1] != '\n')
|
while (bol > gs->buf && bol[-1] != '\n')
|
||||||
bol--;
|
bol--;
|
||||||
cur--;
|
cur--;
|
||||||
|
if (comment_needed && (is_empty_line(bol, eol) ||
|
||||||
|
match_funcname(opt, gs, bol, eol))) {
|
||||||
|
comment_needed = 0;
|
||||||
|
from = orig_from;
|
||||||
|
if (cur < from) {
|
||||||
|
cur++;
|
||||||
|
bol = next_bol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (funcname_needed && match_funcname(opt, gs, bol, eol)) {
|
if (funcname_needed && match_funcname(opt, gs, bol, eol)) {
|
||||||
funcname_lno = cur;
|
funcname_lno = cur;
|
||||||
funcname_needed = 0;
|
funcname_needed = 0;
|
||||||
|
if (opt->funcbody)
|
||||||
|
comment_needed = 1;
|
||||||
|
else
|
||||||
|
from = orig_from;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,10 @@ test_expect_success 'setup' '
|
|||||||
|
|
||||||
check_diff changed_hello 'changed function'
|
check_diff changed_hello 'changed function'
|
||||||
|
|
||||||
|
test_expect_success ' context includes comment' '
|
||||||
|
grep "^ .*Hello comment" changed_hello.diff
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success ' context includes begin' '
|
test_expect_success ' context includes begin' '
|
||||||
grep "^ .*Begin of hello" changed_hello.diff
|
grep "^ .*Begin of hello" changed_hello.diff
|
||||||
'
|
'
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Hello comment.
|
||||||
|
*/
|
||||||
static void hello(void) // Begin of hello
|
static void hello(void) // Begin of hello
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -60,6 +60,18 @@ test_expect_success setup '
|
|||||||
echo " line with leading space3"
|
echo " line with leading space3"
|
||||||
echo "line without leading space2"
|
echo "line without leading space2"
|
||||||
} >space &&
|
} >space &&
|
||||||
|
cat >hello.ps1 <<-\EOF &&
|
||||||
|
# No-op.
|
||||||
|
function dummy() {}
|
||||||
|
|
||||||
|
# Say hello.
|
||||||
|
function hello() {
|
||||||
|
echo "Hello world."
|
||||||
|
} # hello
|
||||||
|
|
||||||
|
# Still a no-op.
|
||||||
|
function dummy() {}
|
||||||
|
EOF
|
||||||
git add . &&
|
git add . &&
|
||||||
test_tick &&
|
test_tick &&
|
||||||
git commit -m initial
|
git commit -m initial
|
||||||
@ -766,18 +778,27 @@ test_expect_success 'grep -W shows no trailing empty lines' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
cat >expected <<EOF
|
|
||||||
hello.c= printf("Hello world.\n");
|
|
||||||
hello.c: return 0;
|
|
||||||
hello.c- /* char ?? */
|
|
||||||
EOF
|
|
||||||
|
|
||||||
test_expect_success 'grep -W with userdiff' '
|
test_expect_success 'grep -W with userdiff' '
|
||||||
test_when_finished "rm -f .gitattributes" &&
|
test_when_finished "rm -f .gitattributes" &&
|
||||||
git config diff.custom.xfuncname "(printf.*|})$" &&
|
git config diff.custom.xfuncname "^function .*$" &&
|
||||||
echo "hello.c diff=custom" >.gitattributes &&
|
echo "hello.ps1 diff=custom" >.gitattributes &&
|
||||||
git grep -W return >actual &&
|
git grep -W echo >function-context-userdiff-actual
|
||||||
test_cmp expected actual
|
'
|
||||||
|
|
||||||
|
test_expect_success ' includes preceding comment' '
|
||||||
|
grep "# Say hello" function-context-userdiff-actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success ' includes function line' '
|
||||||
|
grep "=function hello" function-context-userdiff-actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success ' includes matching line' '
|
||||||
|
grep ": echo" function-context-userdiff-actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success ' includes last line of the function' '
|
||||||
|
grep "} # hello" function-context-userdiff-actual
|
||||||
'
|
'
|
||||||
|
|
||||||
for threads in $(test_seq 0 10)
|
for threads in $(test_seq 0 10)
|
||||||
|
@ -121,6 +121,12 @@ static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri,
|
|||||||
return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv);
|
return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri)
|
||||||
|
{
|
||||||
|
char dummy[1];
|
||||||
|
return match_func_rec(xdf, xecfg, ri, dummy, sizeof(dummy)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct func_line {
|
struct func_line {
|
||||||
long len;
|
long len;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
@ -178,7 +184,6 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
|||||||
|
|
||||||
/* Appended chunk? */
|
/* Appended chunk? */
|
||||||
if (i1 >= xe->xdf1.nrec) {
|
if (i1 >= xe->xdf1.nrec) {
|
||||||
char dummy[1];
|
|
||||||
long i2 = xch->i2;
|
long i2 = xch->i2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -186,8 +191,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
|||||||
* a whole function was added.
|
* a whole function was added.
|
||||||
*/
|
*/
|
||||||
while (i2 < xe->xdf2.nrec) {
|
while (i2 < xe->xdf2.nrec) {
|
||||||
if (match_func_rec(&xe->xdf2, xecfg, i2,
|
if (is_func_rec(&xe->xdf2, xecfg, i2))
|
||||||
dummy, sizeof(dummy)) >= 0)
|
|
||||||
goto post_context_calculation;
|
goto post_context_calculation;
|
||||||
i2++;
|
i2++;
|
||||||
}
|
}
|
||||||
@ -200,6 +204,9 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fs1 = get_func_line(xe, xecfg, NULL, i1, -1);
|
fs1 = get_func_line(xe, xecfg, NULL, i1, -1);
|
||||||
|
while (fs1 > 0 && !is_empty_rec(&xe->xdf1, fs1 - 1) &&
|
||||||
|
!is_func_rec(&xe->xdf1, xecfg, fs1 - 1))
|
||||||
|
fs1--;
|
||||||
if (fs1 < 0)
|
if (fs1 < 0)
|
||||||
fs1 = 0;
|
fs1 = 0;
|
||||||
if (fs1 < s1) {
|
if (fs1 < s1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user