improved get_node(), connect(), etc code completion.

-properly completes text arguments
-includes the "/root" autoloads
This commit is contained in:
Juan Linietsky
2015-06-26 01:14:31 -03:00
parent 71cc2561c6
commit a67486a39e
10 changed files with 211 additions and 26 deletions

View File

@ -381,7 +381,12 @@ static Ref<Reference> _get_parent_class(GDCompletionContext& context) {
path=context.base_path.plus_file(path);
}
script = ResourceLoader::load(path);
if (ScriptCodeCompletionCache::get_sigleton())
script = ScriptCodeCompletionCache::get_sigleton()->get_cached_resource(path);
else
script = ResourceLoader::load(path);
if (script.is_null()) {
return REF();
}
@ -1322,6 +1327,21 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St
if (obj) {
List<String> options;
obj->get_argument_options(p_method,p_argidx,&options);
if (obj->is_type("Node") && p_argidx==0 && (String(p_method)=="get_node" || String(p_method)=="has_node")) {
List<PropertyInfo> props;
Globals::get_singleton()->get_property_list(&props);
for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
String s = E->get().name;
if (!s.begins_with("autoload/"))
continue;
// print_line("found "+s);
String name = s.get_slice("/",1);
options.push_back("\"/root/"+name+"\"");
}
}
for(List<String>::Element *E=options.front();E;E=E->next()) {
result.insert(E->get());
@ -1661,7 +1681,9 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
//print_line( p_code.replace(String::chr(0xFFFF),"<cursor>"));
GDParser p;
Error err = p.parse(p_code,p_base_path,true);
//Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="",bool p_for_completion=false);
Error err = p.parse(p_code,p_base_path,false,"",true);
bool isfunction=false;
Set<String> options;

View File

@ -30,6 +30,7 @@
#include "print_string.h"
#include "io/resource_loader.h"
#include "os/file_access.h"
#include "script_language.h"
template<class T>
T* GDParser::alloc_node() {
@ -116,6 +117,14 @@ bool GDParser::_parse_arguments(Node* p_parent,Vector<Node*>& p_args,bool p_stat
if (tokenizer->get_token()==GDTokenizer::TK_CURSOR) {
_make_completable_call(argidx);
completion_node=p_parent;
} else if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type()==Variant::STRING && tokenizer->get_token(1)==GDTokenizer::TK_CURSOR) {
//completing a string argument..
completion_cursor=tokenizer->get_token_constant();
_make_completable_call(argidx);
completion_node=p_parent;
tokenizer->advance(1);
return false;
}
Node*arg = _parse_expression(p_parent,p_static);
@ -277,7 +286,11 @@ GDParser::Node* GDParser::_parse_expression(Node *p_parent,bool p_static,bool p_
if (!validating) {
//this can be too slow for just validating code
res = ResourceLoader::load(path);
if (for_completion && ScriptCodeCompletionCache::get_sigleton()) {
res = ScriptCodeCompletionCache::get_sigleton()->get_cached_resource(path);
} else {
res = ResourceLoader::load(path);
}
if (!res.is_valid()) {
_set_error("Can't preload resource at path: "+path);
return NULL;
@ -2814,6 +2827,8 @@ Error GDParser::_parse(const String& p_base_path) {
Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path, const String &p_self_path) {
for_completion=false;
validating=false;
completion_type=COMPLETION_NONE;
completion_node=NULL;
completion_class=NULL;
@ -2834,7 +2849,7 @@ Error GDParser::parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p
}
Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_just_validate, const String &p_self_path) {
Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_just_validate, const String &p_self_path,bool p_for_completion) {
completion_type=COMPLETION_NONE;
completion_node=NULL;
@ -2851,6 +2866,7 @@ Error GDParser::parse(const String& p_code, const String& p_base_path, bool p_ju
tt->set_code(p_code);
validating=p_just_validate;
for_completion=p_for_completion;
tokenizer=tt;
Error ret = _parse(p_base_path);
memdelete(tt);
@ -2886,6 +2902,7 @@ void GDParser::clear() {
current_function=NULL;
validating=false;
for_completion=false;
error_set=false;
tab_level.clear();
tab_level.push_back(0);

View File

@ -387,6 +387,7 @@ private:
T* alloc_node();
bool validating;
bool for_completion;
int parenthesis;
bool error_set;
String error;
@ -443,7 +444,7 @@ public:
String get_error() const;
int get_error_line() const;
int get_error_column() const;
Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="");
Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="",bool p_for_completion=false);
Error parse_bytecode(const Vector<uint8_t> &p_bytecode,const String& p_base_path="",const String& p_self_path="");
const Node *get_parse_tree() const;

View File

@ -568,7 +568,10 @@ void GDTokenizerText::_advance() {
} else if( string_mode!=STRING_MULTILINE && CharType(GETCHAR(i))=='\n') {
_make_error("Unexpected EOL at String.");
return;
} else if( CharType(GETCHAR(i))==0xFFFF) {
//string ends here, next will be TK
i--;
break;
} else if (CharType(GETCHAR(i))=='\\') {
//escaped characters...
i++;
@ -670,19 +673,19 @@ void GDTokenizerText::_advance() {
while(true) {
if (GETCHAR(i)=='.') {
if (period_found || exponent_found) {
_make_error("Invalid numeric constant at '.'");
_make_error("Invalid numeric constant at '.'");
return;
}
period_found=true;
} else if (GETCHAR(i)=='x') {
if (hexa_found || str.length()!=1 || !( (i==1 && str[0]=='0') || (i==2 && str[1]=='0' && str[0]=='-') ) ) {
_make_error("Invalid numeric constant at 'x'");
if (hexa_found || str.length()!=1 || !( (i==1 && str[0]=='0') || (i==2 && str[1]=='0' && str[0]=='-') ) ) {
_make_error("Invalid numeric constant at 'x'");
return;
}
hexa_found=true;
} else if (!hexa_found && GETCHAR(i)=='e') {
} else if (!hexa_found && GETCHAR(i)=='e') {
if (hexa_found || exponent_found) {
_make_error("Invalid numeric constant at 'e'");
_make_error("Invalid numeric constant at 'e'");
return;
}
exponent_found=true;
@ -692,7 +695,7 @@ void GDTokenizerText::_advance() {
} else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) {
if (sign_found) {
_make_error("Invalid numeric constant at '-'");
_make_error("Invalid numeric constant at '-'");
return;
}
sign_found=true;
@ -703,20 +706,20 @@ void GDTokenizerText::_advance() {
i++;
}
if (!( _is_number(str[str.length()-1]) || (hexa_found && _is_hex(str[str.length()-1])))) {
_make_error("Invalid numeric constant: "+str);
if (!( _is_number(str[str.length()-1]) || (hexa_found && _is_hex(str[str.length()-1])))) {
_make_error("Invalid numeric constant: "+str);
return;
}
INCPOS(str.length());
if (hexa_found) {
int val = str.hex_to_int();
_make_constant(val);
} else if (period_found) {
if (hexa_found) {
int val = str.hex_to_int();
_make_constant(val);
} else if (period_found) {
real_t val = str.to_double();
//print_line("*%*%*%*% to convert: "+str+" result: "+rtos(val));
_make_constant(val);
} else {
} else {
int val = str.to_int();
_make_constant(val);
@ -825,7 +828,7 @@ void GDTokenizerText::_advance() {
_make_built_in_func(GDFunctions::Function(i));
found=true;
break;
break;
}
}