robotcodedev / robotcode

RobotFramework support for Visual Studio Code
https://robotcode.io
Apache License 2.0
187 stars 15 forks source link

[BUG] VS Code Variables are not resolved within robot.variables for code completion #162

Closed DanielPenning closed 10 months ago

DanielPenning commented 1 year ago

To Reproduce Our settings.json consists of a variable robot variable that internally uses the ${workspaceFolder} variable from VS Code.

"robotcode.robot.variables": {
    "my_app_dir": "${workspaceFolder}/app"
}

When I use the variable from within robot, it displays the proper value, so ${workspaceFolder} is resolved correctly.

*** Test Cases ***
Log Variable With Workspace Folder
    Log To Console    ${my_app_dir}

Output

==============================================================================
Log Variable With Workspace Folder                                    C:\Users\DanielPenning\Source\eval-plugin-robotcode\app
Log Variable With Workspace Folder                                    | PASS |

We use the variable to store a path to a robot library, so actual use is like this:

*** Settings ***
Library    ${ep_app_dir}/MyLibrary.py

Running the test works, but robotcode fails to generate libdoc / code-completion for this. Error message:

Library '${workspaceFolder}\app\MyLibrary.py' does not exist.robotcode.namespace(DataError)

So it seems for the library directive, code completion does not resolve the VS Code variable properly. Can this be changed? We need it both for the library path and the library arguments.

Desktop (please complete the following information):

stlxiii commented 1 year ago

I think I have a similar issue. I declare a variable in a variable file: Variables ${EXECDIR}/libraries/Variables.py

Then on the next line, I import a library and use that variable as an argument. Library ${EXECDIR}/libraries/MyLibrary.py ${MY_VARIABLE_DECLARED_ON_THE_PREVIOUS_LINE}

This works fine when running the tests, but in the editor, MyLibrary is not loaded (so errors everywhere) because: Variable '${MY_VARIABLE_DECLARED_ON_THE_PREVIOUS_LINE}' not found.robotcode.namespace(VariableError)

d-biehl commented 1 year ago

@DanielPenning

You've found an interesting new behavior that I hadn't noticed before, but it's actually unintended. Explaining it is a bit complicated ;-)


The ${workspaceFolder} variable is replaced by the vscode debugging API (means by vscode itself, not the robotcode extension), but you wrote this in the vscode settings file where this variable is not supported, robotcode code completion only gets the setting and doesn't know about any internal vscode variables. This is because RobotCode is only a language server implementation and vscode is just a LSP client and there is nothing defined in the Language Server Protocol about variables in settings. So replacement has to be done in the server component and other LSP Clients like Eclipse/Neovim, and maybe sometimes PyCharm might not support this variable replacement in settings. So I'm not sure if I should implement such variable replacement in the language server part only for vscode,

And yes there is also the RobotCode debugger and the debugger implements the DAP interface, and again there is nothing about settings variables in the DAP protocol.

I have to think about this again...


The RobotFramework way to do such things (and this is independent from any Editor/IDE/Whatever) is to use the ${EXECDIR} variable this contains at runtime the same content like the vscode variable ${workspaceFolder}, so you can write something like this

*** Settings ***
Library    ${EXECDIR}/app/MyLibrary.py

or if you want to have a variable for this like in you example above, write a resource file like this:

file: common_vars.resource

*** Variables ***
${EP_APP_DIR}    ${EXECDIR}/app

and then before you import your library import the resource like:

*** Settings ***
Resource    common_vars.resource
Library   ${EP_APP_DIR}/MyLibrary.py

In my opinion, it's better to configure your test environment in the Robot Framework way and possibly make it selectively overrideable from the outside. This simplifies the configuration for IDEs and also the execution on the command line, for instance, in a CI environment.

with both ways there is no need to change a setting in vscode and you don't need to add extra variables to start your tests from command line. But with the last method you can override the ${EP_APP_DIR} from command line.


The last method is a relativ new thing I am working on, but it is not fully documented, but this is my goal till the end of the year. If you are interessted in, try this:

create a file named robot.toml in you project root folder and put the following content to it:

[variables]
EP_APP_DIR.expr = "Path.cwd() / 'app'"

the robot.toml file should be an IDE/Editor independent configuration file for your robot framework settings, every robot command line option has a corresponding setting in the robot.toml file. Look at https://robotcode.io and then "CLI/Config" for all possible configuration settings.

The RobotCode language server can use this file and on the command line then you can install the robotcode-runner package with pip in to your python environment and then instead running robot like this:

robot -d output --loglevel DEBUG -v A_VARIABLE:12345 -v ANOTHER_VARIABLE:12345 --flatten-keywords  -P whateverpath -i whatevertag path_to_your_tests

you can run your tests in a much shorter way like this:

robotcode robot -i whatevertag

If you install the Even Better TOML Extension to VSCode you will also have some code completions for the robot.toml file.

However, it's important to note that this feature in RobotCode is relatively new and not thoroughly documented yet. if you're willing to give it a try, I would greatly appreciate any feedback you can provide.

d-biehl commented 1 year ago

@stlxiii

Can you provide me with a bit more input? What does your Variables.py look like?

Have you ever tried clearing the RobotCode cache? -> Press F1 and then search for "Robot Code: Clear Cache and Restart Language Servers."

DanielPenning commented 1 year ago

Hi @d-biehl Thanks for the detailed explanations. Your proposals are indeed a workaround, but usability would suffer in our software. We need to think about that. I think there must be a way to resolve vs-code variables for the settings.json robot-variables because with https://marketplace.visualstudio.com/items?itemName=robocorp.robotframework-lsp this used to work.

stlxiii commented 1 year ago

@stlxiii

Can you provide me with a bit more input? What does your Variables.py look like?

Have you ever tried clearing the RobotCode cache? -> Press F1 and then search for "Robot Code: Clear Cache and Restart Language Servers."

I didn't know about that option, and it did fix the problem. Thanks!

DanielPenning commented 10 months ago

@d-biehl I just tried the TOML files you outlined earlier. Everything works really well (including path resolving using the ".expr" syntax). All variables were resolved properly both in VS Code at dev time (shown when hovering above them) and when actually invoking robot.

For dev time, this is a great option for us. For the end user, it is unfortunately a little problematic

But thanks for pointing me to this. And again, it worked flawlessly 👍 I think this ticket here can be closed.

d-biehl commented 10 months ago

Thanks for the feedback, I'll close the issue now.

Regarding the robot.toml: Since I am also supported by the RobotFramework Foundation on this topic, the topic is also known there and there were also the comments that one could imagine that a robot.toml should actually also be supported by Robot directly. But there are no more plans at the moment.

I will present the robotcode.cli tools and robot.toml officially at RoboCon Online on 27 February in a tutorial, by then I will have some more documentation. My plan is also to offer a slot on the topic at the offline RoboCon on Community Day. If you are interested, you can come along ;-)

DanielPenning commented 10 months ago

Ah, thanks for the background info. Official support would be great. I will listen to your Robocon Online talk. My colleague @WisniewskiP will be at Robocon, I will tell him.