|
1 | 1 | #include "ecmascript_language.h" |
2 | 2 | #include "core/class_db.h" |
3 | 3 | #include "core/os/file_access.h" |
| 4 | +#include "editor/plugins/script_editor_plugin.h" |
| 5 | +#include "core/os/os.cpp" |
| 6 | +#include "core/io/json.h" |
4 | 7 | ECMAScriptLanguage *ECMAScriptLanguage::singleton = NULL; |
5 | 8 |
|
6 | 9 | void ECMAScriptLanguage::init() { |
@@ -221,6 +224,105 @@ void ECMAScriptLanguage::reload_all_scripts() { |
221 | 224 | #endif |
222 | 225 | } |
223 | 226 |
|
| 227 | +/** If trying to open a .jsx class with an external editor, and we detect a .tsx it's compiled from, open that instead */ |
| 228 | +Error ECMAScriptLanguage::open_in_external_editor(const Ref<Script>& p_script, int p_line, int p_col) { |
| 229 | + Ref<ECMAScript> s = p_script; |
| 230 | + if (s->get_script_path().ends_with(EXT_JSCLASS)) { |
| 231 | + Error f_err; |
| 232 | + FileAccessRef f = FileAccess::open("res://tsconfig.json", FileAccess::READ, &f_err); |
| 233 | + if (!f) { |
| 234 | + print_line("Failed to read tsconfig.json at project root"); |
| 235 | + return (Error)ERR_UNAVAILABLE; |
| 236 | + } |
| 237 | + |
| 238 | + Error json_parse_err; |
| 239 | + String json = f->get_as_utf8_string(); |
| 240 | + String err_txt; |
| 241 | + int err_line; |
| 242 | + Variant parsed_json; |
| 243 | + json_parse_err = JSON::parse(json, parsed_json, err_txt, err_line); |
| 244 | + if (json_parse_err != OK) { |
| 245 | + print_error("Failed parsing tsconfig.json"); |
| 246 | + return (Error)ERR_UNAVAILABLE; |
| 247 | + } |
| 248 | + |
| 249 | + String ts_root_dir = parsed_json.get("compilerOptions").get("rootDir"); |
| 250 | + ts_root_dir = ts_root_dir.replace_first(".", ""); |
| 251 | + String ts_out_dir = parsed_json.get("compilerOptions").get("outDir"); |
| 252 | + ts_out_dir = ts_out_dir.replace_first(".", ""); |
| 253 | + |
| 254 | + |
| 255 | + String tsx_path = s->get_script_path().replacen(EXT_JSCLASS, EXT_TSCLASS); |
| 256 | + tsx_path = tsx_path.replacen(ts_out_dir, ts_root_dir); |
| 257 | + |
| 258 | + if (!FileAccess::exists(tsx_path)) { |
| 259 | + print_line("TSX file doesn't exist at:"); |
| 260 | + print_line(tsx_path); |
| 261 | + return (Error)ERR_UNAVAILABLE; |
| 262 | + } |
| 263 | + |
| 264 | + String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path"); |
| 265 | + String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags"); |
| 266 | + |
| 267 | + List<String> args; |
| 268 | + bool has_file_flag = false; |
| 269 | + String script_path = ProjectSettings::get_singleton()->globalize_path(tsx_path); |
| 270 | + |
| 271 | + if (flags.size()) { |
| 272 | + String project_path = ProjectSettings::get_singleton()->get_resource_path(); |
| 273 | + |
| 274 | + flags = flags.replacen("{line}", itos(p_line > 0 ? p_line : 0)); |
| 275 | + flags = flags.replacen("{col}", itos(p_col)); |
| 276 | + flags = flags.strip_edges().replace("\\\\", "\\"); |
| 277 | + |
| 278 | + int from = 0; |
| 279 | + int num_chars = 0; |
| 280 | + bool inside_quotes = false; |
| 281 | + |
| 282 | + for (int i = 0; i < flags.size(); i++) { |
| 283 | + |
| 284 | + if (flags[i] == '"' && (!i || flags[i - 1] != '\\')) { |
| 285 | + |
| 286 | + if (!inside_quotes) { |
| 287 | + from++; |
| 288 | + } |
| 289 | + inside_quotes = !inside_quotes; |
| 290 | + |
| 291 | + } else if (flags[i] == '\0' || (!inside_quotes && flags[i] == ' ')) { |
| 292 | + |
| 293 | + String arg = flags.substr(from, num_chars); |
| 294 | + if (arg.find("{file}") != -1) { |
| 295 | + has_file_flag = true; |
| 296 | + } |
| 297 | + |
| 298 | + // do path replacement here, else there will be issues with spaces and quotes |
| 299 | + arg = arg.replacen("{project}", project_path); |
| 300 | + arg = arg.replacen("{file}", script_path); |
| 301 | + args.push_back(arg); |
| 302 | + |
| 303 | + from = i + 1; |
| 304 | + num_chars = 0; |
| 305 | + } else { |
| 306 | + num_chars++; |
| 307 | + } |
| 308 | + } |
| 309 | + } |
| 310 | + |
| 311 | + // Default to passing script path if no {file} flag is specified. |
| 312 | + if (!has_file_flag) { |
| 313 | + args.push_back(script_path); |
| 314 | + } |
| 315 | + |
| 316 | + Error err = OS::get_singleton()->execute(path, args, false); |
| 317 | + if (err == OK) |
| 318 | + return err; |
| 319 | + WARN_PRINT("Couldn't open external text editor, using internal"); |
| 320 | + } |
| 321 | + |
| 322 | + |
| 323 | + return (Error)ERR_UNAVAILABLE; |
| 324 | +} |
| 325 | + |
224 | 326 | void ECMAScriptLanguage::reload_script(const Ref<Script> &p_script, bool p_soft_reload) { |
225 | 327 | Ref<ECMAScript> s = p_script; |
226 | 328 | if (s.is_valid()) { |
|
0 commit comments