Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
godot
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
community
godot
Commits
d35c018a
Commit
d35c018a
authored
Jan 09, 2020
by
geequlim
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GDScript LSP: Implement signatureHelp
Enable smart resolve default to true as it is required for script symbol lookup
parent
bdcfc6d6
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
232 additions
and
1 deletion
+232
-1
gdscript_extend_parser.cpp
modules/gdscript/language_server/gdscript_extend_parser.cpp
+45
-0
gdscript_extend_parser.h
modules/gdscript/language_server/gdscript_extend_parser.h
+2
-0
gdscript_language_server.cpp
...les/gdscript/language_server/gdscript_language_server.cpp
+1
-1
gdscript_text_document.cpp
modules/gdscript/language_server/gdscript_text_document.cpp
+15
-0
gdscript_text_document.h
modules/gdscript/language_server/gdscript_text_document.h
+1
-0
gdscript_workspace.cpp
modules/gdscript/language_server/gdscript_workspace.cpp
+51
-0
gdscript_workspace.h
modules/gdscript/language_server/gdscript_workspace.h
+1
-0
lsp.hpp
modules/gdscript/language_server/lsp.hpp
+116
-0
No files found.
modules/gdscript/language_server/gdscript_extend_parser.cpp
View file @
d35c018a
...
...
@@ -522,6 +522,51 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(i
return
ret
;
}
Error
ExtendGDScriptParser
::
get_left_function_call
(
const
lsp
::
Position
&
p_position
,
lsp
::
Position
&
r_func_pos
,
int
&
r_arg_index
)
const
{
ERR_FAIL_INDEX_V
(
p_position
.
line
,
lines
.
size
(),
ERR_INVALID_PARAMETER
);
int
bracket_stack
=
0
;
int
index
=
0
;
bool
found
=
false
;
for
(
int
l
=
p_position
.
line
;
l
>=
0
;
--
l
)
{
String
line
=
lines
[
l
];
int
c
=
line
.
length
()
-
1
;
if
(
l
==
p_position
.
line
)
{
c
=
MIN
(
c
,
p_position
.
character
-
1
);
}
while
(
c
>=
0
)
{
const
CharType
&
charactor
=
line
[
c
];
if
(
charactor
==
')'
)
{
++
bracket_stack
;
}
else
if
(
charactor
==
'('
)
{
--
bracket_stack
;
if
(
bracket_stack
<
0
)
{
found
=
true
;
}
}
if
(
bracket_stack
<=
0
&&
charactor
==
','
)
{
++
index
;
}
--
c
;
if
(
found
)
{
r_func_pos
.
character
=
c
;
break
;
}
}
if
(
found
)
{
r_func_pos
.
line
=
l
;
r_arg_index
=
index
;
return
OK
;
}
}
return
ERR_METHOD_NOT_FOUND
;
}
const
lsp
::
DocumentSymbol
*
ExtendGDScriptParser
::
get_symbol_defined_at_line
(
int
p_line
)
const
{
if
(
p_line
<=
0
)
{
return
&
class_symbol
;
...
...
modules/gdscript/language_server/gdscript_extend_parser.h
View file @
d35c018a
...
...
@@ -83,6 +83,8 @@ public:
_FORCE_INLINE_
const
ClassMembers
&
get_members
()
const
{
return
members
;
}
_FORCE_INLINE_
const
HashMap
<
String
,
ClassMembers
>
&
get_inner_classes
()
const
{
return
inner_classes
;
}
Error
get_left_function_call
(
const
lsp
::
Position
&
p_position
,
lsp
::
Position
&
r_func_pos
,
int
&
r_arg_index
)
const
;
String
get_text_for_completion
(
const
lsp
::
Position
&
p_cursor
)
const
;
String
get_text_for_lookup_symbol
(
const
lsp
::
Position
&
p_cursor
,
const
String
&
p_symbol
=
""
,
bool
p_func_requred
=
false
)
const
;
String
get_identifier_under_position
(
const
lsp
::
Position
&
p_position
,
Vector2i
&
p_offset
)
const
;
...
...
modules/gdscript/language_server/gdscript_language_server.cpp
View file @
d35c018a
...
...
@@ -38,7 +38,7 @@ GDScriptLanguageServer::GDScriptLanguageServer() {
thread
=
NULL
;
thread_exit
=
false
;
_EDITOR_DEF
(
"network/language_server/remote_port"
,
6008
);
_EDITOR_DEF
(
"network/language_server/enable_smart_resolve"
,
fals
e
);
_EDITOR_DEF
(
"network/language_server/enable_smart_resolve"
,
tru
e
);
_EDITOR_DEF
(
"network/language_server/show_native_symbols_in_editor"
,
false
);
}
...
...
modules/gdscript/language_server/gdscript_text_document.cpp
View file @
d35c018a
...
...
@@ -50,6 +50,7 @@ void GDScriptTextDocument::_bind_methods() {
ClassDB
::
bind_method
(
D_METHOD
(
"hover"
),
&
GDScriptTextDocument
::
hover
);
ClassDB
::
bind_method
(
D_METHOD
(
"definition"
),
&
GDScriptTextDocument
::
definition
);
ClassDB
::
bind_method
(
D_METHOD
(
"declaration"
),
&
GDScriptTextDocument
::
declaration
);
ClassDB
::
bind_method
(
D_METHOD
(
"signatureHelp"
),
&
GDScriptTextDocument
::
signatureHelp
);
ClassDB
::
bind_method
(
D_METHOD
(
"show_native_symbol_in_editor"
),
&
GDScriptTextDocument
::
show_native_symbol_in_editor
);
}
...
...
@@ -387,6 +388,20 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_params) {
return
arr
;
}
Variant
GDScriptTextDocument
::
signatureHelp
(
const
Dictionary
&
p_params
)
{
Variant
ret
;
lsp
::
TextDocumentPositionParams
params
;
params
.
load
(
p_params
);
lsp
::
SignatureHelp
s
;
if
(
OK
==
GDScriptLanguageProtocol
::
get_singleton
()
->
get_workspace
()
->
resolve_signature
(
params
,
s
))
{
ret
=
s
.
to_json
();
}
return
ret
;
}
GDScriptTextDocument
::
GDScriptTextDocument
()
{
file_checker
=
FileAccess
::
create
(
FileAccess
::
ACCESS_RESOURCES
);
}
...
...
modules/gdscript/language_server/gdscript_text_document.h
View file @
d35c018a
...
...
@@ -67,6 +67,7 @@ public:
Variant
hover
(
const
Dictionary
&
p_params
);
Array
definition
(
const
Dictionary
&
p_params
);
Variant
declaration
(
const
Dictionary
&
p_params
);
Variant
signatureHelp
(
const
Dictionary
&
p_params
);
void
initialize
();
...
...
modules/gdscript/language_server/gdscript_workspace.cpp
View file @
d35c018a
...
...
@@ -252,6 +252,12 @@ Error GDScriptWorkspace::initialize() {
bool
arg_default_value_started
=
false
;
for
(
int
j
=
0
;
j
<
data
.
arguments
.
size
();
j
++
)
{
const
DocData
::
ArgumentDoc
&
arg
=
data
.
arguments
[
j
];
lsp
::
DocumentSymbol
symbol_arg
;
symbol_arg
.
name
=
arg
.
name
;
symbol_arg
.
kind
=
lsp
::
SymbolKind
::
Variable
;
symbol_arg
.
detail
=
arg
.
type
;
if
(
!
arg_default_value_started
&&
!
arg
.
default_value
.
empty
())
{
arg_default_value_started
=
true
;
}
...
...
@@ -263,6 +269,8 @@ Error GDScriptWorkspace::initialize() {
arg_str
+=
", "
;
}
params
+=
arg_str
;
symbol
.
children
.
push_back
(
symbol_arg
);
}
if
(
data
.
qualifiers
.
find
(
"vararg"
)
!=
-
1
)
{
params
+=
params
.
empty
()
?
"..."
:
", ..."
;
...
...
@@ -513,6 +521,49 @@ Dictionary GDScriptWorkspace::generate_script_api(const String &p_path) {
return
api
;
}
Error
GDScriptWorkspace
::
resolve_signature
(
const
lsp
::
TextDocumentPositionParams
&
p_doc_pos
,
lsp
::
SignatureHelp
&
r_signature
)
{
if
(
const
ExtendGDScriptParser
*
parser
=
get_parse_result
(
get_file_path
(
p_doc_pos
.
textDocument
.
uri
)))
{
lsp
::
TextDocumentPositionParams
text_pos
;
text_pos
.
textDocument
=
p_doc_pos
.
textDocument
;
if
(
parser
->
get_left_function_call
(
p_doc_pos
.
position
,
text_pos
.
position
,
r_signature
.
activeParameter
)
==
OK
)
{
List
<
const
lsp
::
DocumentSymbol
*>
symbols
;
if
(
const
lsp
::
DocumentSymbol
*
symbol
=
resolve_symbol
(
text_pos
))
{
symbols
.
push_back
(
symbol
);
}
else
if
(
GDScriptLanguageProtocol
::
get_singleton
()
->
is_smart_resolve_enabled
())
{
GDScriptLanguageProtocol
::
get_singleton
()
->
get_workspace
()
->
resolve_related_symbols
(
text_pos
,
symbols
);
}
for
(
List
<
const
lsp
::
DocumentSymbol
*>::
Element
*
E
=
symbols
.
front
();
E
;
E
=
E
->
next
())
{
const
lsp
::
DocumentSymbol
*
symbol
=
E
->
get
();
if
(
symbol
->
kind
==
lsp
::
SymbolKind
::
Method
||
symbol
->
kind
==
lsp
::
SymbolKind
::
Function
)
{
lsp
::
SignatureInformation
signature_info
;
signature_info
.
label
=
symbol
->
detail
;
signature_info
.
documentation
=
symbol
->
render
();
for
(
int
i
=
0
;
i
<
symbol
->
children
.
size
();
i
++
)
{
const
lsp
::
DocumentSymbol
&
arg
=
symbol
->
children
[
i
];
lsp
::
ParameterInformation
arg_info
;
arg_info
.
label
=
arg
.
name
;
signature_info
.
parameters
.
push_back
(
arg_info
);
}
r_signature
.
signatures
.
push_back
(
signature_info
);
break
;
}
}
if
(
r_signature
.
signatures
.
size
())
{
return
OK
;
}
}
}
return
ERR_METHOD_NOT_FOUND
;
}
GDScriptWorkspace
::
GDScriptWorkspace
()
{
ProjectSettings
::
get_singleton
()
->
get_resource_path
();
}
...
...
modules/gdscript/language_server/gdscript_workspace.h
View file @
d35c018a
...
...
@@ -83,6 +83,7 @@ public:
const
lsp
::
DocumentSymbol
*
resolve_native_symbol
(
const
lsp
::
NativeSymbolInspectParams
&
p_params
);
void
resolve_document_links
(
const
String
&
p_uri
,
List
<
lsp
::
DocumentLink
>
&
r_list
);
Dictionary
generate_script_api
(
const
String
&
p_path
);
Error
resolve_signature
(
const
lsp
::
TextDocumentPositionParams
&
p_doc_pos
,
lsp
::
SignatureHelp
&
r_signature
);
GDScriptWorkspace
();
~
GDScriptWorkspace
();
...
...
modules/gdscript/language_server/lsp.hpp
View file @
d35c018a
...
...
@@ -1402,6 +1402,120 @@ struct Hover {
}
};
/**
* Represents a parameter of a callable-signature. A parameter can
* have a label and a doc-comment.
*/
struct
ParameterInformation
{
/**
* The label of this parameter information.
*
* Either a string or an inclusive start and exclusive end offsets within its containing
* signature label. (see SignatureInformation.label). The offsets are based on a UTF-16
* string representation as `Position` and `Range` does.
*
* *Note*: a label of type string should be a substring of its containing signature label.
* Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.
*/
String
label
;
/**
* The human-readable doc-comment of this parameter. Will be shown
* in the UI but can be omitted.
*/
MarkupContent
documentation
;
Dictionary
to_json
()
const
{
Dictionary
dict
;
dict
[
"label"
]
=
label
;
dict
[
"documentation"
]
=
documentation
.
to_json
();
return
dict
;
}
};
/**
* Represents the signature of something callable. A signature
* can have a label, like a function-name, a doc-comment, and
* a set of parameters.
*/
struct
SignatureInformation
{
/**
* The label of this signature. Will be shown in
* the UI.
*/
String
label
;
/**
* The human-readable doc-comment of this signature. Will be shown
* in the UI but can be omitted.
*/
MarkupContent
documentation
;
/**
* The parameters of this signature.
*/
Vector
<
ParameterInformation
>
parameters
;
Dictionary
to_json
()
const
{
Dictionary
dict
;
dict
[
"label"
]
=
label
;
dict
[
"documentation"
]
=
documentation
.
to_json
();
Array
args
;
for
(
int
i
=
0
;
i
<
parameters
.
size
();
i
++
)
{
args
.
push_back
(
parameters
[
i
].
to_json
());
}
dict
[
"parameters"
]
=
args
;
return
dict
;
}
};
/**
* Signature help represents the signature of something
* callable. There can be multiple signature but only one
* active and only one active parameter.
*/
struct
SignatureHelp
{
/**
* One or more signatures.
*/
Vector
<
SignatureInformation
>
signatures
;
/**
* The active signature. If omitted or the value lies outside the
* range of `signatures` the value defaults to zero or is ignored if
* `signatures.length === 0`. Whenever possible implementors should
* make an active decision about the active signature and shouldn't
* rely on a default value.
* In future version of the protocol this property might become
* mandatory to better express this.
*/
int
activeSignature
=
0
;
/**
* The active parameter of the active signature. If omitted or the value
* lies outside the range of `signatures[activeSignature].parameters`
* defaults to 0 if the active signature has parameters. If
* the active signature has no parameters it is ignored.
* In future version of the protocol this property might become
* mandatory to better express the active parameter if the
* active signature does have any.
*/
int
activeParameter
=
0
;
Dictionary
to_json
()
const
{
Dictionary
dict
;
Array
sigs
;
for
(
int
i
=
0
;
i
<
signatures
.
size
();
i
++
)
{
sigs
.
push_back
(
signatures
[
i
].
to_json
());
}
dict
[
"signatures"
]
=
sigs
;
dict
[
"activeSignature"
]
=
activeSignature
;
dict
[
"activeParameter"
]
=
activeParameter
;
return
dict
;
}
};
struct
ServerCapabilities
{
/**
* Defines how text documents are synced. Is either a detailed structure defining each notification or
...
...
@@ -1532,6 +1646,8 @@ struct ServerCapabilities {
Dictionary
dict
;
dict
[
"textDocumentSync"
]
=
(
int
)
textDocumentSync
.
change
;
dict
[
"completionProvider"
]
=
completionProvider
.
to_json
();
signatureHelpProvider
.
triggerCharacters
.
push_back
(
","
);
signatureHelpProvider
.
triggerCharacters
.
push_back
(
"("
);
dict
[
"signatureHelpProvider"
]
=
signatureHelpProvider
.
to_json
();
dict
[
"codeLensProvider"
]
=
false
;
// codeLensProvider.to_json();
dict
[
"documentOnTypeFormattingProvider"
]
=
documentOnTypeFormattingProvider
.
to_json
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment