Skip to content

Commit

Permalink
feat(langserver): goto, highlight, rename, hover, find references for…
Browse files Browse the repository at this point in the history
… named arguments

rename and goto only works for resource keywords
  • Loading branch information
d-biehl committed Aug 15, 2023
1 parent 934e299 commit 054d210
Show file tree
Hide file tree
Showing 3,720 changed files with 32,902 additions and 61,335 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion packages/core/src/robotcode/core/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def __default(o: Any) -> Any:
field,
)
for field in dataclasses.fields(o)
if field.init or field.metadata.get("force_json", False)
if (field.init or field.metadata.get("force_json", False)) and not field.metadata.get("nosave", False)
)
if value is not None or field.default == dataclasses.MISSING
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ async def _analyze_keyword_call(
name, value = split_from_equals(arg.value)
if value is not None and name:
arg_def = next(
(e for e in result.argument_definitions if e.name_token and e.name_token.value == name),
(e for e in result.argument_definitions if e.name[2:-1] == name),
None,
)
if arg_def is not None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,20 @@ def __hash__(self) -> int:
@dataclass
class ArgumentDefinition(VariableDefinition):
type: VariableDefinitionType = VariableDefinitionType.ARGUMENT
keyword_doc: Optional["KeywordDoc"] = None
keyword_doc: Optional["KeywordDoc"] = field(default=None, compare=False, metadata={"nosave": True})

@single_call
def __hash__(self) -> int:
return hash((type(self), self.name, self.type, self.range, self.source))


@dataclass
class LibraryArgumentDefinition(ArgumentDefinition):
@single_call
def __hash__(self) -> int:
return hash((type(self), self.name, self.type, self.range, self.source))


@dataclass(frozen=True, eq=False, repr=False)
class NativeValue:
value: Any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import weakref
import zlib
from abc import ABC, abstractmethod
from ast import walk
from collections import OrderedDict
from concurrent.futures import ProcessPoolExecutor
from dataclasses import dataclass
Expand All @@ -25,7 +24,6 @@
Mapping,
Optional,
Tuple,
cast,
final,
)

Expand All @@ -41,20 +39,14 @@
from robotcode.language_server.common.parts.workspace import FileWatcherEntry, Workspace
from robotcode.language_server.common.text_document import TextDocument
from robotcode.language_server.robotframework.configuration import CacheSaveLocation, RobotCodeConfig
from robotcode.language_server.robotframework.utils.ast_utils import HasError, HasErrors, Token
from robotcode.language_server.robotframework.utils.robot_path import find_file_ex
from robotcode.language_server.robotframework.utils.version import get_robot_version, get_robot_version_str

from ...__version__ import __version__
from .entities import CommandLineVariableDefinition, VariableDefinition
from .library_doc import (
ROBOT_LIBRARY_PACKAGE,
ArgumentSpec,
CompleteResult,
Error,
KeywordArgumentDoc,
KeywordDoc,
KeywordStore,
LibraryDoc,
ModuleSpec,
VariablesDoc,
Expand All @@ -65,9 +57,9 @@
find_library,
find_variables,
get_library_doc,
get_model_doc,
get_module_spec,
get_variables_doc,
is_embedded_keyword,
is_library_by_path,
is_variables_by_path,
resolve_args,
Expand Down Expand Up @@ -1177,121 +1169,10 @@ def get_libdoc_from_model(
scope: str = "GLOBAL",
append_model_errors: bool = True,
) -> LibraryDoc:
from robot.errors import DataError
from robot.libdocpkg.robotbuilder import KeywordDocBuilder
from robot.parsing.lexer.tokens import Token as RobotToken
from robot.parsing.model.statements import KeywordName
from robot.running.builder.transformers import ResourceBuilder
from robot.running.model import ResourceFile
from robot.running.usererrorhandler import UserErrorHandler
from robot.running.userkeyword import UserLibrary

errors: List[Error] = []
keyword_names: List[KeywordName] = []

for node in walk(model):
if isinstance(node, KeywordName):
keyword_names.append(node)

error = node.error if isinstance(node, HasError) else None
if error is not None:
errors.append(Error(message=error, type_name="ModelError", source=source, line_no=node.lineno))
if append_model_errors:
node_errors = node.errors if isinstance(node, HasErrors) else None
if node_errors is not None:
for e in node_errors:
errors.append(Error(message=e, type_name="ModelError", source=source, line_no=node.lineno))

def get_keyword_name_token_from_line(line: int) -> Optional[Token]:
for keyword_name in keyword_names:
if keyword_name.lineno == line:
return cast(Token, keyword_name.get_token(RobotToken.KEYWORD_NAME))

return None

res = ResourceFile(source=source)

ResourceBuilder(res).visit(model)

class MyUserLibrary(UserLibrary):
current_kw: Any = None

def _log_creating_failed(self, handler: UserErrorHandler, error: BaseException) -> None:
err = Error(
message=f"Creating keyword '{handler.name}' failed: {error!s}",
type_name=type(error).__qualname__,
source=self.current_kw.source if self.current_kw is not None else None,
line_no=self.current_kw.lineno if self.current_kw is not None else None,
)
errors.append(err)

def _create_handler(self, kw: Any) -> Any:
self.current_kw = kw
try:
handler = super()._create_handler(kw)
setattr(handler, "errors", None)
except DataError as e:
err = Error(
message=str(e),
type_name=type(e).__qualname__,
source=kw.source,
line_no=kw.lineno,
)
errors.append(err)

handler = UserErrorHandler(e, kw.name, self.name)
handler.source = kw.source
handler.lineno = kw.lineno

setattr(handler, "errors", [err])

return handler

lib = MyUserLibrary(res)

libdoc = LibraryDoc(
name=lib.name or "",
doc=lib.doc,
type=model_type,
scope=scope,
source=source,
line_no=1,
errors=errors,
return get_model_doc(
model=model, source=source, model_type=model_type, scope=scope, append_model_errors=append_model_errors
)

libdoc.keywords = KeywordStore(
source=libdoc.name,
source_type=libdoc.type,
keywords=[
KeywordDoc(
name=kw[0].name,
args=[KeywordArgumentDoc.from_robot(a) for a in kw[0].args],
doc=kw[0].doc,
tags=list(kw[0].tags),
source=str(kw[0].source),
name_token=get_keyword_name_token_from_line(kw[0].lineno),
line_no=kw[0].lineno if kw[0].lineno is not None else -1,
col_offset=-1,
end_col_offset=-1,
end_line_no=-1,
libname=libdoc.name,
libtype=libdoc.type,
longname=f"{libdoc.name}.{kw[0].name}",
is_embedded=is_embedded_keyword(kw[0].name),
errors=getattr(kw[1], "errors") if hasattr(kw[1], "errors") else None,
is_error_handler=isinstance(kw[1], UserErrorHandler),
error_handler_message=str(cast(UserErrorHandler, kw[1]).error)
if isinstance(kw[1], UserErrorHandler)
else None,
arguments=ArgumentSpec.from_robot_argument_spec(kw[1].arguments),
parent=libdoc.digest,
)
for kw in [(KeywordDocBuilder(resource=True).build_keyword(lw), lw) for lw in lib.handlers]
],
)

return libdoc

@_logger.call
async def get_libdoc_for_variables_import(
self,
Expand Down
Loading

0 comments on commit 054d210

Please sign in to comment.