diff --git a/README.adoc b/README.adoc index fb8a340a0..2d048ea40 100644 --- a/README.adoc +++ b/README.adoc @@ -40,7 +40,7 @@ Likewise, the current version of wxPython, is 4.2.1, but RIDE is known to work w `pip install -U robotframework-ride` -(3.8 < python <= 3.12) Install current development version (**2.1dev54**) with: +(3.8 < python <= 3.12) Install current development version (**2.1dev55**) with: `pip install -U https://github.com/robotframework/RIDE/archive/master.zip` diff --git a/src/robotide/controller/cellinfo.py b/src/robotide/controller/cellinfo.py index b14e55654..2227aa929 100644 --- a/src/robotide/controller/cellinfo.py +++ b/src/robotide/controller/cellinfo.py @@ -94,7 +94,8 @@ def _get_message(self, cell): CellType.MUST_BE_EMPTY: self._must_be_empty, CellType.UNKNOWN: self._unknown, CellType.END: self._keyword, - CellType.FOR: self._keyword + CellType.FOR: self._keyword, + CellType.VAR: self._assign } return (handlers[cell.cell_type](cell) + message).strip() @@ -162,7 +163,8 @@ class ContentType: EXCEPT = 'EXCEPT' BREAK = 'BREAK' CONTINUE = 'CONTINUE' - KEYWORDS = (USER_KEYWORD, LIBRARY_KEYWORD, END, FOR, IF, ELSE, ELSEIF, WHILE, TRY, EXCEPT, BREAK, CONTINUE) + VAR = 'VAR' + KEYWORDS = (USER_KEYWORD, LIBRARY_KEYWORD, END, FOR, IF, ELSE, ELSEIF, WHILE, TRY, EXCEPT, BREAK, CONTINUE, VAR) VARIABLE = 'VARIABLE' UNKNOWN_VARIABLE = 'UNKNOWN_VARIABLE' COMMENTED = 'COMMENTED' @@ -187,8 +189,9 @@ class CellType: EXCEPT = 'KEYWORD' BREAK = 'KEYWORD' CONTINUE = 'KEYWORD' + VAR = 'ASSIGN' UPPERCASE_KWS = [ContentType.END, ContentType.FOR, ContentType.IF, ContentType.ELSE, ContentType.ELSEIF, ContentType.WHILE, ContentType.TRY, ContentType.EXCEPT, - ContentType.BREAK, ContentType.CONTINUE, 'IN', 'IN RANGE', 'IN ENUMERATE', 'IN ZIP'] + ContentType.BREAK, ContentType.CONTINUE, ContentType.VAR, 'IN', 'IN RANGE', 'IN ENUMERATE', 'IN ZIP'] diff --git a/src/robotide/controller/stepcontrollers.py b/src/robotide/controller/stepcontrollers.py index 89d7af1a9..31c0e2dfc 100644 --- a/src/robotide/controller/stepcontrollers.py +++ b/src/robotide/controller/stepcontrollers.py @@ -150,7 +150,10 @@ def _get_cell_position(self, column): if info: args = info.arguments args_amount = len(args) - if column > keyword_col and self.get_value(keyword_col) == "FOR" and self.is_assigning(value_at_col): + if (column > keyword_col and (self.get_value(keyword_col) == "FOR" or self.get_value(keyword_col) == "VAR") + and self.is_assigning(value_at_col)): + # print(f"DEBUG: stepcontrollers.py StepController _get_cell_position VAR or FOR assign " + # f"value_at_col={value_at_col}") return CellPosition(CellType.ASSIGN, None) if column <= keyword_col and self.is_assigning(value_at_col): return CellPosition(CellType.ASSIGN, None) diff --git a/src/robotide/lib/robot/parsing/model.py b/src/robotide/lib/robot/parsing/model.py index 73293f923..bbb75ac65 100644 --- a/src/robotide/lib/robot/parsing/model.py +++ b/src/robotide/lib/robot/parsing/model.py @@ -1277,11 +1277,12 @@ def _get_assign(self): self.normal_assign = True if 0 <= index < len(cells) and self.is_kind_of_comment(cells[index]): # Special case for commented content return [] - # print(f"DEBUG: RFLib Model _get_assign VAR NORMAL (index={index}) inner_kw_pos={self.inner_kw_pos} content={content[:]}") + # print(f"DEBUG: RFLib Model _get_assign VAR NORMAL (index={index}) inner_kw_pos={self.inner_kw_pos}" + # f" content={cells[:]}") # first handle non-FOR cases idx = 0 try: - if cells[self.inner_kw_pos] != 'FOR': + if cells[self.inner_kw_pos] != 'FOR' and cells[self.inner_kw_pos] != 'VAR': while idx < len(cells): if is_var(cells[idx].rstrip('=')): assign.append(cells.pop(idx)) @@ -1290,7 +1291,8 @@ def _get_assign(self): else: break idx += 1 - # print(f"DEBUG: RFLib Model _get_assign RETURN assign={assign} size of content={len(content)}") + # print(f"DEBUG: RFLib Model _get_assign RETURN assign={assign} size of content={len(cells)}" + # f" cells[self.inner_kw_pos]={cells[self.inner_kw_pos]}") return assign except IndexError: pass @@ -1300,8 +1302,11 @@ def _get_assign(self): positional = True else: positional = False - if not positional and self.inner_kw_pos < idx <= self.inner_kw_pos + 3 < len(cells) and cells[self.inner_kw_pos] == 'FOR': - # print(f"DEBUG: RFLib Model _get_assign idx={idx} +1{self.inner_kw_pos + 1}:{idx+1} +2{self.inner_kw_pos + 2}:{idx+2}" + if not positional and ((self.inner_kw_pos < idx <= self.inner_kw_pos + 3 < len(cells) and + cells[self.inner_kw_pos] == 'FOR') or + (self.inner_kw_pos < idx < len(cells) and cells[self.inner_kw_pos] == 'VAR')): + # print(f"DEBUG: RFLib Model _get_assign idx={idx} +1{self.inner_kw_pos + 1}: + # {idx+1} +2{self.inner_kw_pos + 2}:{idx+2}" # f"FOR content1={content[self.inner_kw_pos + 1]}" # f" content2={content[self.inner_kw_pos + 2]} size of content={len(content)}") if idx + 2 < len(cells): # idx < self.inner_kw_pos + 3 and @@ -1315,17 +1320,18 @@ def _get_assign(self): if idx == self.inner_kw_pos + 1: positional = True self.normal_assign = False - # print(f"DEBUG: RFLib Model _get_assign FOR idx={idx} first loop var") + # print(f"DEBUG: RFLib Model _get_assign FOR or VAR idx={idx} first loop var") # else: # positional = False - if not positional and self.inner_kw_pos < idx <= self.inner_kw_pos + 1 < len(cells) and re_set_var.match(cells[self.inner_kw_pos]): + if (not positional and self.inner_kw_pos < idx <= self.inner_kw_pos + 1 < len(cells) and + re_set_var.match(cells[self.inner_kw_pos])): positional = True self.normal_assign = False - if is_var(cells[idx].rstrip('=')) and positional: # and self.normal_assign: + if is_var(cells[idx].rstrip('=').strip()) and positional: # and self.normal_assign: assign.append(cells.pop(idx)) idx -= 1 # We need to recheck var in case of IN ENUMERATE idx += 1 - # print(f"DEBUG: RFLib Model _get_assign idx={idx} size of content={len(content)}") + # print(f"DEBUG: RFLib Model _get_assign idx={idx} size of content={len(cells)} RETURN assign={assign}") return assign def is_comment(self): diff --git a/src/robotide/namespace/cache.py b/src/robotide/namespace/cache.py index 04621fbb8..7420687ed 100644 --- a/src/robotide/namespace/cache.py +++ b/src/robotide/namespace/cache.py @@ -201,7 +201,8 @@ def _build_default_kws(self): f'\n\n{var_note}\n\n See `BuiltIn.VAR` docs at\n https://robotframework.org/robotframework/latest/' 'RobotFrameworkUserGuide.html#toc-entry-329.') - obj18 = BlockKeywordInfo('VAR', var_doc, 'ROBOT', 'BuiltIn', ARG_VALUES) + obj18 = BlockKeywordInfo('VAR', var_doc, 'ROBOT', 'BuiltIn', + 'name_of_variable', ARG_VALUES) kws.append(obj18) return kws diff --git a/src/robotide/version.py b/src/robotide/version.py index 16dd4c57d..ff6e9a208 100644 --- a/src/robotide/version.py +++ b/src/robotide/version.py @@ -15,4 +15,4 @@ # # Automatically generated by `tasks.py`. -VERSION = 'v2.1dev54' +VERSION = 'v2.1dev55' diff --git a/utest/controller/test_cellinfo.py b/utest/controller/test_cellinfo.py index 929b38ef5..dc0354788 100644 --- a/utest/controller/test_cellinfo.py +++ b/utest/controller/test_cellinfo.py @@ -18,10 +18,8 @@ import pytest from utest.resources import datafilereader -from robotide.controller.ctrlcommands import ChangeCellValue, delete_rows, AddKeyword, \ - Undo, paste_area -from robotide.controller.cellinfo import CellType, ContentType, CellInfo, \ - CellContent, CellPosition +from robotide.controller.ctrlcommands import ChangeCellValue, delete_rows, AddKeyword, Undo, paste_area +from robotide.controller.cellinfo import CellType, ContentType, CellInfo, CellContent, CellPosition SET_VARIABLE = 'Set Variable' LIB_PY = 'libi.py' @@ -224,6 +222,14 @@ def test_variable_setting(self): self._verify_cell_info(0, 1, ContentType.LIBRARY_KEYWORD, CellType.KEYWORD) self._verify_string_change(0, 2, CellType.OPTIONAL) + def test_variable_defined_by_var(self): + self.test.execute(ChangeCellValue(0, 0, 'VAR')) + self._verify_cell_info(0, 0, ContentType.LIBRARY_KEYWORD, CellType.KEYWORD) + self.test.execute(ChangeCellValue(0, 1, '${my cool var}')) + self._verify_cell_info(0, 1, ContentType.UNKNOWN_VARIABLE, CellType.OPTIONAL) + self.test.execute(ChangeCellValue(0, 2, 'my cool var value')) + self._verify_cell_info(0, 2, ContentType.STRING, CellType.OPTIONAL) + def test_keyword_without_args(self): self.test.execute(ChangeCellValue(0, 0, self.keyword3.name)) self._verify_cell_info(0, 0, ContentType.USER_KEYWORD, CellType.KEYWORD)