Example #1
0
Error GDScriptLanguage::complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_base, List<String>* r_options) {

	GDParser p;
	Error err = p.parse(p_code,p_base_path);
	// don't care much about error I guess
	const GDParser::Node* root = p.get_parse_tree();
	ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_INVALID_DATA);

	const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root);

	List<String> indices;
	Vector<String> spl = p_base.split(".");

	for(int i=0;i<spl.size()-1;i++) {
		indices.push_back(spl[i]);
	}

	if (_parse_completion_class(p_base,cl,p_line,r_options,indices.front()))
		return OK;
	//and the globals x_x?
	for(Map<StringName,int>::Element *E=globals.front();E;E=E->next()) {
		if (!indices.empty()) {
			if (String(E->key())==indices.front()->get()) {

				_parse_completion_variant(global_array[E->get()],r_options,indices.front()->next());

				return OK;
			}
		} else {
			r_options->push_back(E->key());
		}
	}

	return OK;
}
Example #2
0
bool GDScriptLanguage::validate(const String& p_script, int &r_line_error,int &r_col_error,String& r_test_error, const String& p_path,List<String> *r_functions) const {

	GDParser parser;

	Error err = parser.parse(p_script,p_path.get_base_dir(),true);
	if (err) {
		r_line_error=parser.get_error_line();
		r_col_error=parser.get_error_column();
		r_test_error=parser.get_error();
		return false;
	} else {

		const GDParser::Node *root = parser.get_parse_tree();
		ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,false);

		const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root);
		Map<int,String> funcs;
		for(int i=0;i<cl->functions.size();i++) {

			funcs[cl->functions[i]->line]=cl->functions[i]->name;
		}

		for(int i=0;i<cl->static_functions.size();i++) {

			funcs[cl->static_functions[i]->line]=cl->static_functions[i]->name;
		}

		for (Map<int,String>::Element *E=funcs.front();E;E=E->next()) {

			r_functions->push_back(E->get()+":"+itos(E->key()));
		}


	}

	return true;
}
Example #3
0
MainLoop* test(TestType p_test) {

	List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();

	if (cmdlargs.empty()) {
		//try editor!
		return NULL;
	}

	String test = cmdlargs.back()->get();

	FileAccess *fa = FileAccess::open(test,FileAccess::READ);

	if (!fa) {
		ERR_EXPLAIN("Could not open file: "+test);
		ERR_FAIL_V(NULL);
	}


	Vector<uint8_t> buf;
	int flen = fa->get_len();
	buf.resize(fa->get_len()+1);
	fa->get_buffer(&buf[0],flen);
	buf[flen]=0;

	String code;
	code.parse_utf8((const char*)&buf[0]);

	Vector<String> lines;
	int last=0;

	for(int i=0;i<=code.length();i++) {

		if (code[i]=='\n' || code[i]==0) {

			lines.push_back(code.substr(last,i-last));
			last=i+1;
		}
	}


	if (p_test==TEST_TOKENIZER) {

		GDTokenizerText tk;
		tk.set_code(code);
		int line=-1;
		while(tk.get_token()!=GDTokenizer::TK_EOF) {


			String text;
			if (tk.get_token()==GDTokenizer::TK_IDENTIFIER)
				text="'"+tk.get_token_identifier()+"' (identifier)";
			else if (tk.get_token()==GDTokenizer::TK_CONSTANT) {
				Variant c= tk.get_token_constant();
				if (c.get_type()==Variant::STRING)
					text="\""+String(c)+"\"";
				else
					text=c;

				text=text+" ("+Variant::get_type_name(c.get_type())+" constant)";
			} else if (tk.get_token()==GDTokenizer::TK_ERROR)
				text="ERROR: "+tk.get_token_error();
			else if (tk.get_token()==GDTokenizer::TK_NEWLINE)
				text="newline ("+itos(tk.get_token_line())+") + indent: "+itos(tk.get_token_line_indent());
			else if (tk.get_token()==GDTokenizer::TK_BUILT_IN_FUNC)
				text="'"+String(GDFunctions::get_func_name(tk.get_token_built_in_func()))+"' (built-in function)";
			else
				text=tk.get_token_name(tk.get_token());


			if (tk.get_token_line()!=line) {
				int from=line+1;
				line = tk.get_token_line();;

				for(int i=from;i<=line;i++) {
					int l=i-1;
					if (l>=0 && l<lines.size()) {
						print_line("\n"+itos(i)+": "+lines[l]+"\n");
					}
				}
			}
			print_line("\t("+itos(tk.get_token_column())+"): "+text);
			tk.advance();

		}
	}

	if (p_test==TEST_PARSER) {


		GDParser parser;
		Error err = parser.parse(code);
		if (err) {
			print_line("Parse Error:\n"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
			memdelete(fa);
			return NULL;

		}

		const GDParser::Node* root = parser.get_parse_tree();
		ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,NULL);
		const GDParser::ClassNode *cnode=static_cast<const GDParser::ClassNode*>(root);

		_parser_show_class(cnode,0,lines);

	}

	if (p_test==TEST_COMPILER) {


		GDParser parser;

		Error err = parser.parse(code);
		if (err) {
			print_line("Parse Error:\n"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
			memdelete(fa);
			return NULL;

		}

		GDScript *script = memnew( GDScript );

		GDCompiler gdc;
		err = gdc.compile(&parser,script);
		if (err) {

			print_line("Compile Error:\n"+itos(gdc.get_error_line())+":"+itos(gdc.get_error_column())+":"+gdc.get_error());
			memdelete(script);
			return NULL;

		}


		Ref<GDScript> gds =Ref<GDScript>( script );

		Ref<GDScript> current=gds;

		while(current.is_valid()) {

			print_line("** CLASS **");
			_disassemble_class(current,lines);

			current=current->get_base();
		}




	} else if (p_test==TEST_BYTECODE) {

		Vector<uint8_t> buf = GDTokenizerBuffer::parse_code_string(code);
		String dst = test.basename()+".gdc";
		FileAccess *fw = FileAccess::open(dst,FileAccess::WRITE);
		fw->store_buffer(buf.ptr(),buf.size());
		memdelete(fw);
	}


#if 0
	Parser parser;
	Error err = parser.parse(code);
	if (err) {
		print_line("error:"+itos(parser.get_error_line())+":"+itos(parser.get_error_column())+":"+parser.get_error());
	} else {
		print_line("Parse O-K!");
	}
#endif



	memdelete(fa);

	return NULL;
}
Example #4
0
Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base_path, Object*p_owner, List<String>* r_options, String &r_call_hint) {
/* bugs:
  a[0].<complete> does not work
  functions should end in (
  when completing virtuals, ask for full back

 */
	//print_line( p_code.replace(String::chr(0xFFFF),"<cursor>"));

	GDParser p;
	Error err = p.parse(p_code,p_base_path);
	bool isfunction=false;
	Set<String> options;

	GDCompletionContext context;
	context._class=p.get_completion_class();
	context.block=p.get_completion_block();
	context.function=p.get_completion_function();
	context.base=p_owner;
	context.base_path=p_base_path;

	switch(p.get_completion_type()) {

		case GDParser::COMPLETION_NONE: {
			print_line("No completion");
		} break;
		case GDParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
			print_line("Built in type constant");
			List<StringName> constants;
			Variant::get_numeric_constants_for_type(p.get_completion_built_in_constant(),&constants);
			for(List<StringName>::Element *E=constants.front();E;E=E->next()) {
				options.insert(E->get().operator String());
			}


		} break;
		case GDParser::COMPLETION_FUNCTION:
			isfunction=true;
		case GDParser::COMPLETION_IDENTIFIER: {

			_find_identifiers(context,p.get_completion_line(),isfunction,options);
		} break;
		case GDParser::COMPLETION_PARENT_FUNCTION: {
			print_line("parent function");

		} break;
		case GDParser::COMPLETION_METHOD:
			isfunction=true;
		case GDParser::COMPLETION_INDEX: {

			const GDParser::Node *node = p.get_completion_node();
			if (node->type!=GDParser::Node::TYPE_OPERATOR)
				break;




			GDCompletionIdentifier t;
			if (_guess_expression_type(context,static_cast<const GDParser::OperatorNode *>(node)->arguments[0],p.get_completion_line(),t)) {

				if (t.type==Variant::OBJECT && t.obj_type!=StringName()) {


					if (t.value.get_type()) {
						Object *obj=t.value;
						if (obj) {
							GDScript *scr = obj->cast_to<GDScript>();
							while (scr) {

								if (!isfunction) {
									for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) {
										options.insert(E->key());
									}
								}
								for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
									options.insert(E->key());
								}

								if (scr->get_base().is_valid())
									scr=scr->get_base().ptr();
								else
									scr=NULL;
							}
						}
					}


					if (!isfunction) {
						ObjectTypeDB::get_integer_constant_list(t.obj_type,r_options);
					}
					List<MethodInfo> mi;
					ObjectTypeDB::get_method_list(t.obj_type,&mi);
					for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) {

						if (E->get().name.begins_with("_"))
							continue;

						if (E->get().arguments.size())
							options.insert(E->get().name+"(");
						else
							options.insert(E->get().name+"()");

					}
				} else {

					if (t.value.get_type()==Variant::NIL) {
						Variant::CallError ce;
						t.value=Variant::construct(t.type,NULL,0,ce);
					}

					if (!isfunction) {
						List<PropertyInfo> pl;
						t.value.get_property_list(&pl);
						for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) {

							if (E->get().name.find("/")==-1)
								options.insert(E->get().name);
						}
					}

					List<MethodInfo> mi;
					t.value.get_method_list(&mi);
					for (List<MethodInfo>::Element *E=mi.front();E;E=E->next()) {
						if (E->get().arguments.size())
							options.insert(E->get().name+"(");
						else
							options.insert(E->get().name+"()");

					}
				}
			}


		} break;
		case GDParser::COMPLETION_CALL_ARGUMENTS: {

			_find_call_arguments(context,p.get_completion_node(),p.get_completion_line(),p.get_completion_argument_index(),options,r_call_hint);
		} break;


	}


	for(Set<String>::Element *E=options.front();E;E=E->next()) {
		r_options->push_back(E->get());
	}

	return OK;
}