diff options
author | KunMing Xie <qqzz014@gmail.com> | 2018-01-25 18:26:47 +0800 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2018-01-25 11:26:47 +0100 |
commit | 8b1f7d8774b235ae4f0dc0fa64d58e3cad9f8283 (patch) | |
tree | cbd6682b648eb1b9617654eb1d41a61a957e6abd /src | |
parent | a3daa8cb136c83c2fc0e5c9283cde1f7a8ce246c (diff) | |
download | rneovim-8b1f7d8774b235ae4f0dc0fa64d58e3cad9f8283.tar.gz rneovim-8b1f7d8774b235ae4f0dc0fa64d58e3cad9f8283.tar.bz2 rneovim-8b1f7d8774b235ae4f0dc0fa64d58e3cad9f8283.zip |
vim-patch:8.0.0431 (#7908)
vim-patch:8.0.0431: 'cinoptions' cannot set indent for extern block
Problem: 'cinoptions' cannot set indent for extern block.
Solution: Add the "E" flag in 'cinoptions'. (Hirohito Higashi)
https://github.com/vim/vim/commit/7720ba8599162fbbb8f7fc034f674a2ccd3ca7f1
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/indent_c.c | 62 | ||||
-rw-r--r-- | src/nvim/testdir/test_cindent.vim | 60 |
3 files changed, 118 insertions, 5 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 5702ceaaef..8de4286216 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -718,6 +718,7 @@ struct file_buffer { int b_ind_hash_comment; int b_ind_cpp_namespace; int b_ind_if_for_while; + int b_ind_cpp_extern_c; linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary * write should not have an end-of-line */ diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 53364c0fc5..2a215f854f 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -1314,6 +1314,43 @@ static int cin_starts_with(char_u *s, char *word) return STRNCMP(s, word, l) == 0 && !vim_isIDc(s[l]); } +/// Recognize a `extern "C"` or `extern "C++"` linkage specifications. +static int cin_is_cpp_extern_c(char_u *s) +{ + char_u *p; + int has_string_literal = false; + + s = cin_skipcomment(s); + if (STRNCMP(s, "extern", 6) == 0 && (s[6] == NUL || !vim_iswordc(s[6]))) { + p = cin_skipcomment(skipwhite(s + 6)); + while (*p != NUL) { + if (ascii_iswhite(*p)) { + p = cin_skipcomment(skipwhite(p)); + } else if (*p == '{') { + break; + } else if (p[0] == '"' && p[1] == 'C' && p[2] == '"') { + if (has_string_literal) { + return false; + } + has_string_literal = true; + p += 3; + } else if (p[0] == '"' && p[1] == 'C' && p[2] == '+' && p[3] == '+' + && p[4] == '"') { + if (has_string_literal) { + return false; + } + has_string_literal = true; + p += 5; + } else { + return false; + } + } + return has_string_literal ? true : false; + } + return false; +} + + /* * Skip strings, chars and comments until at or past "trypos". * Return the column found. @@ -1322,14 +1359,19 @@ static int cin_skip2pos(pos_T *trypos) { char_u *line; char_u *p; + char_u *new_p; p = line = ml_get(trypos->lnum); while (*p && (colnr_T)(p - line) < trypos->col) { - if (cin_iscomment(p)) + if (cin_iscomment(p)) { p = cin_skipcomment(p); - else { - p = skip_string(p); - ++p; + } else { + new_p = skip_string(p); + if (new_p == p) { + p++; + } else { + p = new_p; + } } } return (int)(p - line); @@ -1622,6 +1664,9 @@ void parse_cino(buf_T *buf) // indentation for # comments buf->b_ind_hash_comment = 0; + // Handle C++ extern "C" or "C++" + buf->b_ind_cpp_extern_c = 0; + for (p = buf->b_p_cino; *p; ) { l = p++; if (*p == '-') @@ -1690,6 +1735,7 @@ void parse_cino(buf_T *buf) case '#': buf->b_ind_hash_comment = n; break; case 'N': buf->b_ind_cpp_namespace = n; break; case 'k': buf->b_ind_if_for_while = n; break; + case 'E': buf->b_ind_cpp_extern_c = n; break; } if (*p == ',') ++p; @@ -2320,8 +2366,11 @@ int get_c_indent(void) amount += curbuf->b_ind_open_imag; l = skipwhite(get_cursor_line_ptr()); - if (cin_is_cpp_namespace(l)) + if (cin_is_cpp_namespace(l)) { amount += curbuf->b_ind_cpp_namespace; + } else if (cin_is_cpp_extern_c(l)) { + amount += curbuf->b_ind_cpp_extern_c; + } } else { /* Compensate for adding b_ind_open_extra later. */ amount -= curbuf->b_ind_open_extra; @@ -2520,6 +2569,9 @@ int get_c_indent(void) amount += curbuf->b_ind_cpp_namespace - added_to_amount; break; + } else if (cin_is_cpp_extern_c(l)) { + amount += curbuf->b_ind_cpp_extern_c - added_to_amount; + break; } if (cin_nocode(l)) diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim index 5685c2be66..444c4c4109 100644 --- a/src/nvim/testdir/test_cindent.vim +++ b/src/nvim/testdir/test_cindent.vim @@ -14,3 +14,63 @@ func Test_cino_hash() call assert_equal(["#include <iostream>", "#include"], getline(1,2)) bwipe! endfunc + +func Test_cino_extern_c() + " Test for cino-E + + let without_ind = [ + \ '#ifdef __cplusplus', + \ 'extern "C" {', + \ '#endif', + \ 'int func_a(void);', + \ '#ifdef __cplusplus', + \ '}', + \ '#endif' + \ ] + + let with_ind = [ + \ '#ifdef __cplusplus', + \ 'extern "C" {', + \ '#endif', + \ "\tint func_a(void);", + \ '#ifdef __cplusplus', + \ '}', + \ '#endif' + \ ] + new + setlocal cindent cinoptions=E0 + call setline(1, without_ind) + call feedkeys("gg=G", 'tx') + call assert_equal(with_ind, getline(1, '$')) + + setlocal cinoptions=E-s + call setline(1, with_ind) + call feedkeys("gg=G", 'tx') + call assert_equal(without_ind, getline(1, '$')) + + setlocal cinoptions=Es + let tests = [ + \ ['recognized', ['extern "C" {'], "\t\t;"], + \ ['recognized', ['extern "C++" {'], "\t\t;"], + \ ['recognized', ['extern /* com */ "C"{'], "\t\t;"], + \ ['recognized', ['extern"C"{'], "\t\t;"], + \ ['recognized', ['extern "C"', '{'], "\t\t;"], + \ ['not recognized', ['extern {'], "\t;"], + \ ['not recognized', ['extern /*"C"*/{'], "\t;"], + \ ['not recognized', ['extern "C" //{'], ";"], + \ ['not recognized', ['extern "C" /*{*/'], ";"], + \ ] + + for pair in tests + let lines = pair[1] + call setline(1, lines) + call feedkeys(len(lines) . "Go;", 'tx') + call assert_equal(pair[2], getline(len(lines) + 1), 'Failed for "' . string(lines) . '"') + endfor + + + + bwipe! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab |