Skip to content

Commit

Permalink
Snippets take into account the value of `robot.completions.keywords.a…
Browse files Browse the repository at this point in the history
…rgumentsSeparator`. Fixes #723
  • Loading branch information
fabioz committed Sep 7, 2022
1 parent 80f4d7c commit eca707e
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 35 deletions.
11 changes: 8 additions & 3 deletions robotframework-ls/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ NEXT

### New features

- Completions presented for `Variables` under `*** Settings ***`. [#744](https://github.com/robocorp/robotframework-lsp/issues/744).
- Completions presented for `Variables` under `*** Settings ***`. [#744](https://github.com/robocorp/robotframework-lsp/issues/744)
- Flow Explorer can now follow keywords defined in other files.

### Bugfixes

- Snippets take into account the value of `robot.completions.keywords.argumentsSeparator`. [#723](https://github.com/robocorp/robotframework-lsp/issues/723)


New in 1.1.0 (2022-08-24)
-----------------------------

Expand All @@ -18,8 +23,8 @@ New in 1.1.0 (2022-08-24)
- Opt-in through the `robot.lint.unusedKeyword:true` setting. [#722](https://github.com/robocorp/robotframework-lsp/issues/722)
- An LRU based on file size now prevents unlimited usage of RAM when caching files loaded from the filesystem. [#720](https://github.com/robocorp/robotframework-lsp/issues/720)
- It's possible to customize the size of the target memory for this LRU through the `RFLS_FILES_TARGET_MEMORY_IN_BYTES` environment variable.
- If a keyword call resolves to multiple keywords, the argument analysis is done for all the matches. [#724](https://github.com/robocorp/robotframework-lsp/issues/724).
- (Experimental) Support for localization in Robot Framework 5.1. [#728](https://github.com/robocorp/robotframework-lsp/issues/728).
- If a keyword call resolves to multiple keywords, the argument analysis is done for all the matches. [#724](https://github.com/robocorp/robotframework-lsp/issues/724)
- (Experimental) Support for localization in Robot Framework 5.1. [#728](https://github.com/robocorp/robotframework-lsp/issues/728)
- The language may be set just for a file (with `language: <lang>` on the top of the file).
- The language may be specified globally through the setting: `robot.language`.
- Support for completions with translated section names and settings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"FOR IN": {
"prefix": "FOR IN",
"body": [
"FOR ${${1:element}} IN @{${2:LIST}}",
" Log ${${1:element}}",
"FOR<sp>${${1:element}}<sp>IN<sp>@{${2:LIST}}",
" Log<sp>${${1:element}}",
" $0",
"END",
],
Expand All @@ -16,8 +16,8 @@
"FOR IN ENUMERATE": {
"prefix": "FOR IN ENUMERATE",
"body": [
"FOR ${${1:index}} ${${2:element}} IN ENUMERATE @{${3:LIST}}",
" Log ${${1:index}}: ${${2:element}}",
"FOR<sp>${${1:index}}<sp>${${2:element}}<sp>IN ENUMERATE<sp>@{${3:LIST}}",
" Log<sp>${${1:index}}: ${${2:element}}",
" $0",
"END",
],
Expand All @@ -26,8 +26,8 @@
"FOR IN RANGE": {
"prefix": "FOR IN RANGE",
"body": [
"FOR ${${1:counter}} IN RANGE ${2:START} ${3:END} ${4:opt.STEPS}",
" Log ${${1:counter}}",
"FOR<sp>${${1:counter}}<sp>IN RANGE<sp>${2:START}<sp>${3:END}<sp>${4:opt.STEPS}",
" Log<sp>${${1:counter}}",
" $0",
"END",
],
Expand All @@ -36,22 +36,22 @@
"FOR IN ZIP": {
"prefix": "FOR IN ZIP",
"body": [
"FOR ${${1:l1-element}} ${${2:l2-element}} IN ZIP ${${3:LIST-1}} ${${4:LIST-2}}",
" Log ${${1:l1-element}} - ${${2:l2-element}}",
"FOR<sp>${${1:l1-element}}<sp>${${2:l2-element}}<sp>IN ZIP<sp>${${3:LIST-1}}<sp>${${4:LIST-2}}",
" Log<sp>${${1:l1-element}} - ${${2:l2-element}}",
" $0",
"END",
],
"description": "Snippet of a FOR IN ZIP loop\n\nA for loop that iterates over two lists and assigns the values from the first list to the first variable and values from the second list to the second variable per iteration.",
},
"IF STATEMENT": {
"prefix": "IF STATEMENT",
"body": ["IF ${${1:var1}} == ${${1:var2}}", " $0", "END"],
"body": ["IF<sp>${${1:var1}} == ${${1:var2}}", " $0", "END"],
"description": "Snippet of an IF..END statement.",
},
"IF ELSE STATEMENT": {
"prefix": "IF ELSE STATEMENT",
"body": [
"IF ${${1:var1}} == ${${1:var2}}",
"IF<sp>${${1:var1}} == ${${1:var2}}",
" ${3:Call Keyword}",
"ELSE",
" $0",
Expand All @@ -62,22 +62,22 @@
"Run Keyword If": {
"prefix": "Run Keyword If",
"body": [
"Run Keyword If ${1:condition}",
"... ${3:Keyword} ${4:@args}",
"... ELSE IF ${2:condition}",
"... ${5:Keyword} ${6:@args}",
"Run Keyword If<sp>${1:condition}",
"... ${3:Keyword}<sp>${4:@args}",
"... ELSE IF<sp>${2:condition}",
"... ${5:Keyword}<sp>${6:@args}",
"... ELSE",
"... ${7:Keyword} ${8:@args}",
"... ${7:Keyword}<sp>${8:@args}",
],
"description": "Runs the given keyword with the given arguments, if condition is true.",
},
"Run Keywords": {
"prefix": "Run Keywords",
"body": [
"Run Keywords",
"... ${1:Keyword} ${2:@args}",
"... ${1:Keyword}<sp>${2:@args}",
"... AND",
"... ${3:Keyword} ${4:@args}",
"... ${3:Keyword}<sp>${4:@args}",
],
"description": "Executes all the given keywords in a sequence.",
},
Expand All @@ -86,12 +86,20 @@
_SNIPPETS_RF5 = {
"TRY EXCEPT STATEMENT": {
"prefix": "TRY EXCEPT",
"body": ["TRY", " $0", "EXCEPT message", " ", "END"],
"body": ["TRY", " $0", "EXCEPT<sp>message", " ", "END"],
"description": "Snippet of a TRY..EXCEPT statement",
},
"TRY EXCEPT FINALLY STATEMENT": {
"prefix": "TRY EXCEPT FINALLY",
"body": ["TRY", " $0", "EXCEPT message", " ", "FINALLY", " ", "END"],
"body": [
"TRY",
" $0",
"EXCEPT<sp>message",
" ",
"FINALLY",
" ",
"END",
],
"description": "Snippet of a TRY..EXCEPT..FINALLY statement",
},
"TRY FINALLY STATEMENT": {
Expand All @@ -101,7 +109,7 @@
},
"WHILE STATEMENT": {
"prefix": "WHILE",
"body": [r"WHILE ${1:expression}", " $0", "END"],
"body": [r"WHILE<sp>${1:expression}", " $0", "END"],
"description": "Snippet of a WHILE statement",
},
}
Expand All @@ -125,7 +133,9 @@ def _get_global_snippets():
return _SNIPPETS_SORTED


def _create_completion_item_from_snippet(label, snippet, selection, line_to_col):
def _create_completion_item_from_snippet(
label, snippet, selection, line_to_col, separator_spaces
):
"""
:param selection: DocumentSelection
"""
Expand All @@ -140,7 +150,7 @@ def _create_completion_item_from_snippet(label, snippet, selection, line_to_col)

current_col = selection.col

text = "\n".join(snippet["body"])
text = "\n".join(snippet["body"]).replace("<sp>", separator_spaces)

text_edit = TextEdit(
Range(
Expand All @@ -155,7 +165,7 @@ def _create_completion_item_from_snippet(label, snippet, selection, line_to_col)
kind=CompletionItemKind.Snippet,
text_edit=text_edit,
insertText=text_edit.newText,
documentation=snippet["description"] + "\n".join(["", ""] + snippet["body"]),
documentation=snippet["description"] + "\n\n" + text,
insertTextFormat=InsertTextFormat.Snippet,
).to_dict()

Expand All @@ -166,16 +176,29 @@ def complete(completion_context: ICompletionContext) -> List[CompletionItemTyped
:param CompletionContext completion_context:
"""
from robotframework_ls.impl.robot_generated_lsp_constants import (
OPTION_ROBOT_COMPLETIONS_KEYWORDS_ARGUMENTS_SEPARATOR,
)

sel = completion_context.sel #::type sel: DocumentSelection
line_to_column = sel.line_to_column.lstrip().lower()
if not line_to_column:
return []

separator_spaces = " "
config = completion_context.config
if config is not None:
separator_spaces = config.get_setting(
OPTION_ROBOT_COMPLETIONS_KEYWORDS_ARGUMENTS_SEPARATOR, str, " "
)

ret = []
for label, data in _get_global_snippets():
if line_to_column in data["prefix"].lower():
ret.append(
_create_completion_item_from_snippet(label, data, sel, line_to_column)
_create_completion_item_from_snippet(
label, data, sel, line_to_column, separator_spaces
)
)

return ret
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
import re
import tempfile
from robocorp_ls_core.command_dispatcher import _CommandDispatcher
from robocorp_ls_core.python_ls import PythonLanguageServer
Expand All @@ -12,7 +11,7 @@
import time
from robotframework_ls.constants import DEFAULT_COMPLETIONS_TIMEOUT
from robocorp_ls_core.robotframework_log import get_logger
from typing import Any, Optional, Dict, Sequence, Generator, Set, ContextManager
from typing import Any, Optional, Dict, Sequence, Set, ContextManager
from robocorp_ls_core.protocols import (
IConfig,
IWorkspace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,23 @@ def test_snippets_completions3(data_regression):
data_regression.check(
completions, basename="test_snippets_completions_try_" + _get_version()
)


def test_snippets_completions_and_spacing(data_regression):
from robotframework_ls.impl.completion_context import CompletionContext
from robotframework_ls.impl.robot_workspace import RobotDocument
from robotframework_ls.impl import snippets_completions
from robotframework_ls.robot_config import RobotConfig
from robotframework_ls.impl.robot_generated_lsp_constants import (
OPTION_ROBOT_COMPLETIONS_KEYWORDS_ARGUMENTS_SEPARATOR,
)

config = RobotConfig()
config.update({OPTION_ROBOT_COMPLETIONS_KEYWORDS_ARGUMENTS_SEPARATOR: " "})

doc = RobotDocument("unused", source="""t""")
completions = snippets_completions.complete(CompletionContext(doc, config=config))

data_regression.check(
completions, basename="test_snippets_completions_2_spaces_" + _get_version()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
- deprecated: false
documentation: "Snippet of a FOR IN ENUMERATE loop.\n\nA for loop that iterates\
\ over a list of values and assigns the iteration index to the first and the value\
\ to the second variable per iteration.\n\nFOR ${${1:index}} ${${2:element}}\
\ IN ENUMERATE @{${3:LIST}}\n Log ${${1:index}}: ${${2:element}}\n $0\n\
END"
insertText: "FOR ${${1:index}} ${${2:element}} IN ENUMERATE @{${3:LIST}}\n \
\ Log ${${1:index}}: ${${2:element}}\n $0\nEND"
insertTextFormat: 2
kind: 15
label: FOR IN ENUMERATE
preselect: false
textEdit:
newText: "FOR ${${1:index}} ${${2:element}} IN ENUMERATE @{${3:LIST}}\n \
\ Log ${${1:index}}: ${${2:element}}\n $0\nEND"
range:
end:
character: 1
line: 0
start:
character: 0
line: 0
- deprecated: false
documentation: "Snippet of an IF..ELSE..END statement\n\nIF ${${1:var1}} == ${${1:var2}}\n\
\ ${3:Call Keyword}\nELSE\n $0\nEND"
insertText: "IF ${${1:var1}} == ${${1:var2}}\n ${3:Call Keyword}\nELSE\n \
\ $0\nEND"
insertTextFormat: 2
kind: 15
label: IF ELSE STATEMENT
preselect: false
textEdit:
newText: "IF ${${1:var1}} == ${${1:var2}}\n ${3:Call Keyword}\nELSE\n $0\n\
END"
range:
end:
character: 1
line: 0
start:
character: 0
line: 0
- deprecated: false
documentation: "Snippet of an IF..END statement.\n\nIF ${${1:var1}} == ${${1:var2}}\n\
\ $0\nEND"
insertText: "IF ${${1:var1}} == ${${1:var2}}\n $0\nEND"
insertTextFormat: 2
kind: 15
label: IF STATEMENT
preselect: false
textEdit:
newText: "IF ${${1:var1}} == ${${1:var2}}\n $0\nEND"
range:
end:
character: 1
line: 0
start:
character: 0
line: 0
Loading

0 comments on commit eca707e

Please sign in to comment.