forked from datawhale/whale-town-front
fix: 修复聊天系统编译错误
- 修复 WebSocketManager/SocketIOClient 函数缩进错误 - 重命名 is_connected() 避免与 Object 基类冲突 - 修复 tscn 文件多余前导空格 - 修复测试文件 GUT 断言函数调用 - 添加 GUT 测试框架
This commit is contained in:
207
addons/gut/editor_caret_context_notifier.gd
Normal file
207
addons/gut/editor_caret_context_notifier.gd
Normal file
@@ -0,0 +1,207 @@
|
||||
@tool
|
||||
extends Node
|
||||
# ##############################################################################
|
||||
#
|
||||
# Watches script editors and emits a signal whenever the method, inner class,
|
||||
# or script changes based on cursor position and other stuff.
|
||||
#
|
||||
# Basically, whenever this thing's signal is emitted, then the RunAtCursor
|
||||
# buttons should be updated to match the data passed to the signal.
|
||||
# ##############################################################################
|
||||
# In the editor, whenever a script is opened you get these new things that
|
||||
# hang off of EditorInterface.get_script_editor()
|
||||
# * ScriptEditorBase
|
||||
# * CodeEdit
|
||||
# ##############################################################################
|
||||
|
||||
|
||||
var _last_info : Dictionary = {}
|
||||
var _last_line = -1
|
||||
# This is the control that holds all the individual editors.
|
||||
var _current_script_editor : ScriptEditor = null
|
||||
# Reference to the GDScript for the last script we were notified about.
|
||||
var _current_script = null
|
||||
var _current_script_is_test_script = false
|
||||
var _current_editor_base : ScriptEditorBase = null
|
||||
var _current_editor : CodeEdit = null
|
||||
# Quick lookup of editors based on the current script.
|
||||
var _editors_for_scripts : Dictionary= {}
|
||||
|
||||
|
||||
# In order to keep the data that comes back from the emitted signal way more
|
||||
# usable, we have to know what GUT looks for for an inner-test-class prefix.
|
||||
# If we didn't do this, then this thing would have to return all the inner
|
||||
# classes and then we'd have to determine if we were in an inner-test-class
|
||||
# outside of here by traversing all the classes returned. It makes this thing
|
||||
# less generic and know too much, but this is probably already too generic as
|
||||
# it is.
|
||||
var inner_class_prefix = "Test"
|
||||
var method_prefix = "test_"
|
||||
var script_prefix = "test_"
|
||||
var script_suffix = ".gd"
|
||||
|
||||
|
||||
# Based on cursor and open editors, this will be emitted. You do what you
|
||||
# want with it.
|
||||
signal it_changed(change_data)
|
||||
|
||||
|
||||
func _ready():
|
||||
# This will not change, and should not change, over the course of a session.
|
||||
_current_script_editor = EditorInterface.get_script_editor()
|
||||
_current_script_editor.editor_script_changed.connect(_on_editor_script_changed)
|
||||
_current_script_editor.script_close.connect(_on_editor_script_close)
|
||||
|
||||
|
||||
func _handle_caret_location(which):
|
||||
var current_line = which.get_caret_line(0) + 1
|
||||
if(_last_line != current_line):
|
||||
_last_line = current_line
|
||||
|
||||
if(_current_script_is_test_script):
|
||||
var new_info = _make_info(which, _current_script, _current_script_is_test_script)
|
||||
if(_last_info != new_info):
|
||||
_last_info = new_info
|
||||
it_changed.emit(_last_info.duplicate())
|
||||
|
||||
|
||||
func _get_func_name_from_line(text):
|
||||
text = text.strip_edges()
|
||||
var left = text.split("(")[0]
|
||||
var func_name = left.split(" ")[1]
|
||||
return func_name
|
||||
|
||||
|
||||
func _get_class_name_from_line(text):
|
||||
text = text.strip_edges()
|
||||
var right = text.split(" ")[1]
|
||||
var the_name = right.rstrip(":")
|
||||
return the_name
|
||||
|
||||
|
||||
func _make_info(editor, script, test_script_flag):
|
||||
if(editor == null):
|
||||
return
|
||||
|
||||
var info = {
|
||||
script = script,
|
||||
inner_class = null,
|
||||
method = null,
|
||||
is_test_script = test_script_flag
|
||||
}
|
||||
|
||||
var start_line = editor.get_caret_line()
|
||||
var line = start_line
|
||||
var done_func = false
|
||||
var done_inner = false
|
||||
while(line > 0 and (!done_func or !done_inner)):
|
||||
if(editor.can_fold_line(line)):
|
||||
var text = editor.get_line(line)
|
||||
var strip_text = text.strip_edges(true, false) # only left
|
||||
|
||||
if(!done_func and strip_text.begins_with("func ")):
|
||||
info.method = _get_func_name_from_line(text)
|
||||
done_func = true
|
||||
# If the func line is left justified then there won't be any
|
||||
# inner classes above it.
|
||||
if(editor.get_indent_level(line) == 0):
|
||||
done_inner = true
|
||||
|
||||
if(!done_inner and strip_text.begins_with("class")):
|
||||
var inner_name = _get_class_name_from_line(text)
|
||||
# See note about inner_class_prefix, this knows too much, but
|
||||
# if it was to know less it would insanely more difficult
|
||||
# everywhere.
|
||||
if(inner_name.begins_with(inner_class_prefix)):
|
||||
info.inner_class = inner_name
|
||||
done_inner = true
|
||||
done_func = true
|
||||
line -= 1
|
||||
|
||||
# print('parsed lines: ', start_line - line, '(', info.inner_class, ':', info.method, ')')
|
||||
return info
|
||||
# -------------
|
||||
# Events
|
||||
# -------------
|
||||
|
||||
# Fired whenever the script changes. This does not fire if you select something
|
||||
# other than a script from the tree. So if you click a help file and then
|
||||
# back to the same file, then this will fire for the same script
|
||||
#
|
||||
# This can fire multiple times for the same script when a script is opened.
|
||||
func _on_editor_script_changed(script):
|
||||
_last_line = -1
|
||||
_current_script = script
|
||||
_current_editor_base = _current_script_editor.get_current_editor()
|
||||
if(_current_editor_base.get_base_editor() is CodeEdit):
|
||||
_current_editor = _current_editor_base.get_base_editor()
|
||||
if(!_current_editor.caret_changed.is_connected(_on_caret_changed)):
|
||||
_current_editor.caret_changed.connect(_on_caret_changed.bind(_current_editor))
|
||||
else:
|
||||
_current_editor = null
|
||||
_editors_for_scripts[script] = _current_editor
|
||||
_current_script_is_test_script = is_test_script(_current_script)
|
||||
|
||||
_handle_caret_location(_current_editor)
|
||||
|
||||
|
||||
func _on_editor_script_close(script):
|
||||
var script_editor = _editors_for_scripts.get(script, null)
|
||||
if(script_editor != null):
|
||||
if(script_editor.caret_changed.is_connected(_on_caret_changed)):
|
||||
script_editor.caret_changed.disconnect(_on_caret_changed)
|
||||
_editors_for_scripts.erase(script)
|
||||
|
||||
|
||||
func _on_caret_changed(which):
|
||||
# Sometimes this is fired for editors that are not the current. I could
|
||||
# make this fire by saving a file in an external editor. I was unable to
|
||||
# get useful data out when it wasn't the current editor so I'm only doing
|
||||
# anything when it is the current editor.
|
||||
if(which == _current_editor):
|
||||
_handle_caret_location(which)
|
||||
|
||||
|
||||
func _could_be_test_script(script):
|
||||
return script.resource_path.get_file().begins_with(script_prefix) and \
|
||||
script.resource_path.get_file().ends_with(script_suffix)
|
||||
|
||||
# -------------
|
||||
# Public
|
||||
# -------------
|
||||
var _scripts_that_have_been_warned_about = []
|
||||
var _we_have_warned_enough = false
|
||||
var _max_warnings = 5
|
||||
func is_test_script(script):
|
||||
var base = script.get_base_script()
|
||||
if(base == null and script.get_script_method_list().size() == 0 and _could_be_test_script(script)):
|
||||
if(OS.is_stdout_verbose() or (!_scripts_that_have_been_warned_about.has(script.resource_path) and !_we_have_warned_enough)):
|
||||
_scripts_that_have_been_warned_about.append(script.resource_path)
|
||||
push_warning(str('[GUT] Treating ', script.resource_path, " as test script: ",
|
||||
"GUT was not able to retrieve information about this script. If this is ",
|
||||
"a new script you can ignore this warning. Otherwise, this may ",
|
||||
"have to do with having VSCode open. Restarting Godot sometimes helps. See ",
|
||||
"https://github.com/bitwes/Gut/issues/754"))
|
||||
if(!OS.is_stdout_verbose() and _scripts_that_have_been_warned_about.size() >= _max_warnings):
|
||||
print("[GUT] Disabling warning.")
|
||||
_we_have_warned_enough = true
|
||||
|
||||
# We can't know if this is a test script. It's more usable if we
|
||||
# assume this is a test script.
|
||||
return true
|
||||
else:
|
||||
while(base and base.resource_path != 'res://addons/gut/test.gd'):
|
||||
base = base.get_base_script()
|
||||
return base != null
|
||||
|
||||
|
||||
func get_info():
|
||||
return _last_info.duplicate()
|
||||
|
||||
|
||||
func log_values():
|
||||
print("---------------------------------------------------------------")
|
||||
print("script ", _current_script)
|
||||
print("script_editor ", _current_script_editor)
|
||||
print("editor_base ", _current_editor_base)
|
||||
print("editor ", _current_editor)
|
||||
Reference in New Issue
Block a user