Mercurial > vim
comparison src/vim9compile.c @ 28281:bd1dcc605e58 v8.2.4666
patch 8.2.4666: Vim9: assignment not recognized in skipped block
Commit: https://github.com/vim/vim/commit/97f8c1081ec6d6d158bb51e18fa23a36d3ed5623
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Apr 2 19:43:57 2022 +0100
patch 8.2.4666: Vim9: assignment not recognized in skipped block
Problem: Vim9: assignment not recognized in skipped block.
Solution: When skipping assume identifier exists. (closes https://github.com/vim/vim/issues/10059)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 02 Apr 2022 20:45:03 +0200 |
parents | 662d2d5db9a6 |
children | 060fc3b69697 |
comparison
equal
deleted
inserted
replaced
28280:e998d4284855 | 28281:bd1dcc605e58 |
---|---|
277 || find_imported(name, len, FALSE) != NULL; | 277 || find_imported(name, len, FALSE) != NULL; |
278 } | 278 } |
279 | 279 |
280 /* | 280 /* |
281 * Return TRUE if "name" is a local variable, argument, script variable, | 281 * Return TRUE if "name" is a local variable, argument, script variable, |
282 * imported or function. | 282 * imported or function. Or commands are being skipped, a declaration may have |
283 * been skipped then. | |
283 */ | 284 */ |
284 static int | 285 static int |
285 item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx) | 286 item_exists(char_u *name, size_t len, int cmd UNUSED, cctx_T *cctx) |
286 { | 287 { |
287 return variable_exists(name, len, cctx); | 288 return variable_exists(name, len, cctx); |
1107 */ | 1108 */ |
1108 int | 1109 int |
1109 get_var_dest( | 1110 get_var_dest( |
1110 char_u *name, | 1111 char_u *name, |
1111 assign_dest_T *dest, | 1112 assign_dest_T *dest, |
1112 int cmdidx, | 1113 cmdidx_T cmdidx, |
1113 int *option_scope, | 1114 int *option_scope, |
1114 int *vimvaridx, | 1115 int *vimvaridx, |
1115 type_T **type, | 1116 type_T **type, |
1116 cctx_T *cctx) | 1117 cctx_T *cctx) |
1117 { | 1118 { |
1223 } | 1224 } |
1224 return OK; | 1225 return OK; |
1225 } | 1226 } |
1226 | 1227 |
1227 static int | 1228 static int |
1228 is_decl_command(int cmdidx) | 1229 is_decl_command(cmdidx_T cmdidx) |
1229 { | 1230 { |
1230 return cmdidx == CMD_let || cmdidx == CMD_var | 1231 return cmdidx == CMD_let || cmdidx == CMD_var |
1231 || cmdidx == CMD_final || cmdidx == CMD_const; | 1232 || cmdidx == CMD_final || cmdidx == CMD_const; |
1232 } | 1233 } |
1233 | 1234 |
1236 * of ":unlet" with an index. | 1237 * of ":unlet" with an index. |
1237 * Returns OK or FAIL. | 1238 * Returns OK or FAIL. |
1238 */ | 1239 */ |
1239 int | 1240 int |
1240 compile_lhs( | 1241 compile_lhs( |
1241 char_u *var_start, | 1242 char_u *var_start, |
1242 lhs_T *lhs, | 1243 lhs_T *lhs, |
1243 int cmdidx, | 1244 cmdidx_T cmdidx, |
1244 int heredoc, | 1245 int heredoc, |
1245 int oplen, | 1246 int has_cmd, // "var" before "var_start" |
1246 cctx_T *cctx) | 1247 int oplen, |
1248 cctx_T *cctx) | |
1247 { | 1249 { |
1248 char_u *var_end; | 1250 char_u *var_end; |
1249 int is_decl = is_decl_command(cmdidx); | 1251 int is_decl = is_decl_command(cmdidx); |
1250 | 1252 |
1251 CLEAR_POINTER(lhs); | 1253 CLEAR_POINTER(lhs); |
1491 { | 1493 { |
1492 // +=, /=, etc. require an existing variable | 1494 // +=, /=, etc. require an existing variable |
1493 semsg(_(e_cannot_use_operator_on_new_variable), lhs->lhs_name); | 1495 semsg(_(e_cannot_use_operator_on_new_variable), lhs->lhs_name); |
1494 return FAIL; | 1496 return FAIL; |
1495 } | 1497 } |
1496 if (!is_decl) | 1498 if (!is_decl || (lhs->lhs_has_index && !has_cmd |
1499 && cctx->ctx_skip != SKIP_YES)) | |
1497 { | 1500 { |
1498 semsg(_(e_unknown_variable_str), lhs->lhs_name); | 1501 semsg(_(e_unknown_variable_str), lhs->lhs_name); |
1499 return FAIL; | 1502 return FAIL; |
1500 } | 1503 } |
1501 | 1504 |
1518 { | 1521 { |
1519 char_u *after = var_start + lhs->lhs_varlen; | 1522 char_u *after = var_start + lhs->lhs_varlen; |
1520 char_u *p; | 1523 char_u *p; |
1521 | 1524 |
1522 // Something follows after the variable: "var[idx]" or "var.key". | 1525 // Something follows after the variable: "var[idx]" or "var.key". |
1523 if (is_decl) | 1526 if (is_decl && cctx->ctx_skip != SKIP_YES) |
1524 { | 1527 { |
1525 emsg(_(e_cannot_use_index_when_declaring_variable)); | 1528 if (has_cmd) |
1529 emsg(_(e_cannot_use_index_when_declaring_variable)); | |
1530 else | |
1531 semsg(_(e_unknown_variable_str), lhs->lhs_name); | |
1526 return FAIL; | 1532 return FAIL; |
1527 } | 1533 } |
1528 | 1534 |
1529 // Now: var_start[lhs->lhs_varlen] is '[' or '.' | 1535 // Now: var_start[lhs->lhs_varlen] is '[' or '.' |
1530 // Only the last index is used below, if there are others | 1536 // Only the last index is used below, if there are others |
1560 /* | 1566 /* |
1561 * Figure out the LHS and check a few errors. | 1567 * Figure out the LHS and check a few errors. |
1562 */ | 1568 */ |
1563 int | 1569 int |
1564 compile_assign_lhs( | 1570 compile_assign_lhs( |
1565 char_u *var_start, | 1571 char_u *var_start, |
1566 lhs_T *lhs, | 1572 lhs_T *lhs, |
1567 int cmdidx, | 1573 cmdidx_T cmdidx, |
1568 int is_decl, | 1574 int is_decl, |
1569 int heredoc, | 1575 int heredoc, |
1570 int oplen, | 1576 int has_cmd, // "var" before "var_start" |
1571 cctx_T *cctx) | 1577 int oplen, |
1572 { | 1578 cctx_T *cctx) |
1573 if (compile_lhs(var_start, lhs, cmdidx, heredoc, oplen, cctx) == FAIL) | 1579 { |
1580 if (compile_lhs(var_start, lhs, cmdidx, heredoc, has_cmd, oplen, cctx) | |
1581 == FAIL) | |
1574 return FAIL; | 1582 return FAIL; |
1575 | 1583 |
1576 if (!lhs->lhs_has_index && lhs->lhs_lvar == &lhs->lhs_arg_lvar) | 1584 if (!lhs->lhs_has_index && lhs->lhs_lvar == &lhs->lhs_arg_lvar) |
1577 { | 1585 { |
1578 semsg(_(e_cannot_assign_to_argument), lhs->lhs_name); | 1586 semsg(_(e_cannot_assign_to_argument), lhs->lhs_name); |
2047 | 2055 |
2048 /* | 2056 /* |
2049 * Figure out the LHS type and other properties. | 2057 * Figure out the LHS type and other properties. |
2050 */ | 2058 */ |
2051 if (compile_assign_lhs(var_start, &lhs, cmdidx, | 2059 if (compile_assign_lhs(var_start, &lhs, cmdidx, |
2052 is_decl, heredoc, oplen, cctx) == FAIL) | 2060 is_decl, heredoc, var_start > eap->cmd, |
2061 oplen, cctx) == FAIL) | |
2053 goto theend; | 2062 goto theend; |
2054 if (heredoc) | 2063 if (heredoc) |
2055 { | 2064 { |
2056 SOURCING_LNUM = start_lnum; | 2065 SOURCING_LNUM = start_lnum; |
2057 if (lhs.lhs_has_type | 2066 if (lhs.lhs_has_type |
2767 } | 2776 } |
2768 | 2777 |
2769 CLEAR_FIELD(ea); | 2778 CLEAR_FIELD(ea); |
2770 ea.cmdlinep = &line; | 2779 ea.cmdlinep = &line; |
2771 ea.cmd = skipwhite(line); | 2780 ea.cmd = skipwhite(line); |
2781 ea.skip = cctx.ctx_skip == SKIP_YES; | |
2772 | 2782 |
2773 if (*ea.cmd == '#') | 2783 if (*ea.cmd == '#') |
2774 { | 2784 { |
2775 // "#" starts a comment | 2785 // "#" starts a comment |
2776 line = (char_u *)""; | 2786 line = (char_u *)""; |
2955 ea.cmdidx = CMD_legacy; | 2965 ea.cmdidx = CMD_legacy; |
2956 } | 2966 } |
2957 | 2967 |
2958 if (p == ea.cmd && ea.cmdidx != CMD_SIZE) | 2968 if (p == ea.cmd && ea.cmdidx != CMD_SIZE) |
2959 { | 2969 { |
2960 if (cctx.ctx_skip == SKIP_YES && ea.cmdidx != CMD_eval) | 2970 // "eval" is used for "val->func()" and "var" for "var = val", then |
2971 // "p" is equal to "ea.cmd" for a valid command. | |
2972 if (ea.cmdidx == CMD_eval || ea.cmdidx == CMD_var) | |
2973 ; | |
2974 else if (cctx.ctx_skip == SKIP_YES) | |
2961 { | 2975 { |
2962 line += STRLEN(line); | 2976 line += STRLEN(line); |
2963 goto nextline; | 2977 goto nextline; |
2964 } | 2978 } |
2965 else if (ea.cmdidx != CMD_eval) | 2979 else |
2966 { | 2980 { |
2967 // CMD_var cannot happen, compile_assignment() above would be | |
2968 // used. Most likely an assignment to a non-existing variable. | |
2969 semsg(_(e_command_not_recognized_str), ea.cmd); | 2981 semsg(_(e_command_not_recognized_str), ea.cmd); |
2970 goto erret; | 2982 goto erret; |
2971 } | 2983 } |
2972 } | 2984 } |
2973 | 2985 |