Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support VAR syntax in RenameVariables #612

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions docs/releasenotes/unreleased/transformers.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
New VAR syntax support in RenameVariables
------------------------------------------

Robot Framework 7.0 introduces new syntax for creating variables: ``VAR``. It is now also supported in Robotidy in
``RenameVariables`` transformer:

Example renaming variables based on the scope. From:

```
*** Test Cases ***
# Create a local variable `${local}` with a value `value`.
VAR ${local} value

# Create a variable that is available throughout the whole suite.
# Supported scopes are GLOBAL, SUITE, TEST, TASK and LOCAL (default).
VAR ${suite} value scope=SUITE
VAR ${global} value scope=GLOBAL
VAR ${test} value scope=TEST
VAR ${task} value scope=TASK
VAR ${local_default} value scope=local

# Validate created variables.
Should Be Equal ${local} value
Should Be Equal ${suite} value
Should Be Equal ${global} value
Should Be Equal ${test} value
Should Be Equal ${task} value
```

To:

```
# Create a local variable `${local}` with a value `value`.
VAR ${local} value

# Create a variable that is available throughout the whole suite.
# Supported scopes are GLOBAL, SUITE, TEST, TASK and LOCAL (default).
VAR ${SUITE} value scope=SUITE
VAR ${GLOBAL} value scope=GLOBAL
VAR ${TEST} value scope=TEST
VAR ${TASK} value scope=TASK
VAR ${local_default} value scope=local

# Validate created variables.
Should Be Equal ${local} value
Should Be Equal ${SUITE} value
Should Be Equal ${GLOBAL} value
Should Be Equal ${TEST} value
Should Be Equal ${TASK} value
```
15 changes: 11 additions & 4 deletions docs/source/transformers/RenameVariables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ Allowed values are:
- ``lower`` to lowercase unknown names
- ``ignore`` to leave existing case

Scope of the variable can be also changed using ``Set Test/Task/Suite/Global Variable`` keywords and with Robot
Framework 7.0 ``VAR`` syntax using ``scope=local/TEST/TASK/SUITE/GLOBAL`` parameter.

.. tab-set::

.. tab-item:: Before
Expand All @@ -135,7 +138,8 @@ Allowed values are:
Keyword
[Arguments] ${arg} # ${arg} is known
${local} Set Variable value # since we set it, ${local} is also known
Keyword Call ${arg} ${local} ${global} # ${global} is unknown
VAR ${local2} value # default scope is local
Keyword Call ${arg} ${local} ${local2} ${global} # ${global} is unknown

.. tab-item:: After (unknown_variables_case = upper)

Expand All @@ -145,7 +149,8 @@ Allowed values are:
Keyword
[Arguments] ${arg} # ${arg} is known
${local} Set Variable value # since we set it, ${local} is also known
Keyword Call ${arg} ${local} ${GLOBAL} # ${global} is unknown
VAR ${local2} value # default scope is local
Keyword Call ${arg} ${local} ${local2} ${GLOBAL} # ${global} is unknown

.. tab-item:: After (unknown_variables_case = lower)

Expand All @@ -155,7 +160,8 @@ Allowed values are:
Keyword
[Arguments] ${arg} # ${arg} is known
${local} Set Variable value # since we set it, ${local} is also known
Keyword Call ${arg} ${local} ${global} # ${global} is unknown
VAR ${local2} value # default scope is local
Keyword Call ${arg} ${local} ${local2} ${global} # ${global} is unknown

.. tab-item:: After (unknown_variables_case = ignore)

Expand All @@ -165,7 +171,8 @@ Allowed values are:
Keyword
[Arguments] ${arg} # ${arg} is known
${local} Set Variable value # since we set it, ${local} is also known
Keyword Call ${arg} ${local} ${global} # ${global} is unknown
VAR ${local2} value # default scope is local
Keyword Call ${arg} ${local} ${local2} ${global} # ${global} is unknown

Ignore variable case
--------------------
Expand Down
21 changes: 21 additions & 0 deletions robotidy/transformers/RenameVariables.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,27 @@ def visit_While(self, node): # noqa
arg.value = self.rename_value(arg.value, variable_case="auto", is_var=False)
return self.generic_visit(node)

@skip_if_disabled
def visit_Var(self, node): # noqa
if node.errors:
return node
for argument in node.get_tokens(Token.ARGUMENT):
argument.value = self.rename_value(argument.value, variable_case="auto", is_var=False)
variable = node.get_token(Token.VARIABLE)
if variable:
if self._is_var_scope_local(node):
self.variables_scope.add_local(variable.value)
variable.value = self.rename_value(variable.value, variable_case="auto", is_var=False)
return node

@staticmethod
def _is_var_scope_local(node):
is_local = True
for option in node.get_tokens(Token.OPTION):
if "scope=" in option.value:
is_local = option.value.lower() == "scope=local"
return is_local

def rename_value(self, value: str, variable_case: str, is_var: bool = False):
try:
variables = list(variable_matcher.VariableMatches(value))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
*** Test Cases ***
Long value
VAR ${long}
... This value is rather long.
... It has been split to multiple lines.
... Parts will be joined together with a space.

Multiline
VAR ${multiline}
... First line.
... Second line.
... Last line.
... separator=\n

Change scope
# Create a local variable `${local}` with a value `value`.
VAR ${local} value

# Create a variable that is available throughout the whole suite.
# Supported scopes are GLOBAL, SUITE, TEST, TASK and LOCAL (default).
VAR ${SUITE} value scope=SUITE
VAR ${GLOBAL} value scope=GLOBAL
VAR ${TEST} value scope=TEST
VAR ${TASK} value scope=TASK
VAR ${local_default} value scope=local

# Validate created variables.
Should Be Equal ${local} value
Should Be Equal ${SUITE} value
Should Be Equal ${GLOBAL} value
Should Be Equal ${TEST} value
Should Be Equal ${TASK} value
IF $local_default
Log Should be lowercase
ELSE IF $suite
Log Should be uppercase # Known issue, before VAR
ELSE IF $global is None
Log Should be uppercase # Known issue, before VAR
END
# if the scope is dynamic, make it global anyway
VAR ${VARIABLE} value scope=${dynamic_scope}
Log ${VARIABLE}

List
# Creates a list with three items.
VAR @{list} a b c
Log ${list}

Dictionary
# Creates a dictionary with two items.
VAR &{dict} key=value second=item
Log ${dict}

Normal IF
IF 1 > 0
VAR ${x} true value
ELSE
VAR ${x} false value
END
Log ${x}

Inline IF
IF 1 > 0 VAR ${x} true value ELSE VAR ${x} false value
Log ${x}

Escaped
VAR $variable
# escaped syntax not supported in definition - variable not defined so scope stays global
Log ${VARIABLE}

*** Keywords ***
Assignment signs
VAR ${variable} = value
VAR ${variable2}= value
Log ${variable}
Log ${variable2}

Dynamic Values
VAR ${variable} with ${GLOBAL} and ${VARIABLE}
VAR ${variable} with ${GLOBAL} and ${variable}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
*** Test Cases ***
Long value
VAR ${long}
... This value is rather long.
... It has been split to multiple lines.
... Parts will be joined together with a space.

Multiline
VAR ${multiline}
... First line.
... Second line.
... Last line.
... separator=\n

Change scope
# Create a local variable `${local}` with a value `value`.
VAR ${local} value

# Create a variable that is available throughout the whole suite.
# Supported scopes are GLOBAL, SUITE, TEST, TASK and LOCAL (default).
VAR ${suite} value scope=SUITE
VAR ${global} value scope=GLOBAL
VAR ${test} value scope=TEST
VAR ${task} value scope=TASK
VAR ${local_default} value scope=local

# Validate created variables.
Should Be Equal ${local} value
Should Be Equal ${suite} value
Should Be Equal ${global} value
Should Be Equal ${test} value
Should Be Equal ${task} value
IF $local_default
Log Should be lowercase
ELSE IF $suite
Log Should be uppercase # Known issue, before VAR
ELSE IF $global is None
Log Should be uppercase # Known issue, before VAR
END
# if the scope is dynamic, make it global anyway
VAR ${variable} value scope=${dynamic_scope}
Log ${variable}

List
# Creates a list with three items.
VAR @{list} a b c
Log ${list}

Dictionary
# Creates a dictionary with two items.
VAR &{dict} key=value second=item
Log ${dict}

Normal IF
IF 1 > 0
VAR ${x} true value
ELSE
VAR ${x} false value
END
Log ${x}

Inline IF
IF 1 > 0 VAR ${x} true value ELSE VAR ${x} false value
Log ${x}

Escaped
VAR $variable
# escaped syntax not supported in definition - variable not defined so scope stays global
Log ${variable}

*** Keywords ***
Assignment signs
VAR ${variable} = value
VAR ${variable2}= value
Log ${variable}
Log ${variable2}

Dynamic Values
VAR ${variable} with ${global} and ${variable}
VAR ${variable} with ${GLOBAL} and ${variable}
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,9 @@ def test_exclude_configure_ignore_vars(self):

def test_extended_variables_syntax(self):
self.compare(source="math_operations.robot")

def test_var_syntax(self):
self.compare(
source="VAR_syntax.robot",
target_version=">6.1.1",
)
Loading