From 7b01dce943ae02f370a58e5fbf926ccf6aaf9f00 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Fri, 28 Nov 2025 21:52:05 +0700 Subject: [PATCH] feat(go): rewrite in Go --- circular-dependency-checker/README.md | 6 +- .../circular_dependency_checker.py | 955 --------------- circular-dependency-checker/go.mod | 3 + circular-dependency-checker/go.sum | 2 + circular-dependency-checker/main.go | 1044 +++++++++++++++++ 5 files changed, 1054 insertions(+), 956 deletions(-) delete mode 100644 circular-dependency-checker/circular_dependency_checker.py create mode 100644 circular-dependency-checker/go.mod create mode 100644 circular-dependency-checker/go.sum create mode 100644 circular-dependency-checker/main.go diff --git a/circular-dependency-checker/README.md b/circular-dependency-checker/README.md index f8fdb8e..fffafbd 100644 --- a/circular-dependency-checker/README.md +++ b/circular-dependency-checker/README.md @@ -1,2 +1,6 @@ # circular-dependency-checker -Detect cyclic dependencies in Godot, which cause "bad address index". Inspired by https://gist.github.com/tavurth/0d4c49a0a800cbc27f80c3a68f0c8ee7 +Detects cyclic dependencies in Godot Engine projects, which cause "bad address index" errors. This tool analyzes `.gd` script files to identify circular dependencies between classes. + +*In 2025, I rewrote this project using Go. The Python version of this project can be found at [feature/python](https://github.com/tiennm99/circular-dependency-checker/tree/feature/python) branch.* + +**Note: This Go version hasn't been tested yet. I don't work with GD projects anymore.** diff --git a/circular-dependency-checker/circular_dependency_checker.py b/circular-dependency-checker/circular_dependency_checker.py deleted file mode 100644 index ea4aab2..0000000 --- a/circular-dependency-checker/circular_dependency_checker.py +++ /dev/null @@ -1,955 +0,0 @@ -import os -import re -import networkx as nx - - -def build_class_graph(directory): - """Builds a directed acyclic graph of class dependencies.""" - # Create a graph to store the dependencies - graph = nx.DiGraph() - - # Find all .gd files in the directory - for root, dirs, files in os.walk(directory): - for file in files: - if not file.endswith(".gd"): - continue - - file_path = os.path.join(root, file) - # Find the class name in the file - with open(file_path, "r", encoding='utf8') as f: - contents = f.read() - match = re.search(r"^class_name\s+(\w+)", contents, re.MULTILINE) - if not match: - continue - - class_name = match.group(1) - graph.add_node(class_name) - - # Find the dependencies of the class - for dep_match in re.finditer( - r"^\s*extends\s+(\w+)", contents, re.MULTILINE - ): - dep_name = dep_match.group(1) - if is_ignored_types(dep_name) or dep_name == class_name: - continue - print(dep_name) - graph.add_edge(class_name, dep_name) - - for dep_match in re.finditer( - r"^.*:\s*(\w+).*\n", contents, re.MULTILINE - ): - dep_name = dep_match.group(1) - if is_ignored_types(dep_name) or dep_name == class_name: - continue - print(dep_name) - graph.add_edge(class_name, dep_name) - - for dep_match in re.finditer( - r"^.*->\s*(\w+).*\n", contents, re.MULTILINE - ): - dep_name = dep_match.group(1) - if is_ignored_types(dep_name) or dep_name == class_name: - continue - print(dep_name) - graph.add_edge(class_name, dep_name) - - for dep_match in re.finditer( - r"^.*Array\[(\w+)].*\n", contents, re.MULTILINE - ): - dep_name = dep_match.group(1) - if is_ignored_types(dep_name) or dep_name == class_name: - continue - print(dep_name) - graph.add_edge(class_name, dep_name) - return graph - - -def find_circular_dependencies(directory): - """Finds circular dependencies between classes in the directory.""" - graph = build_class_graph(directory) - - for cycle in nx.simple_cycles(graph): - print(cycle) - - -# From https://docs.godotengine.org/en/stable/classes/index.html -def is_ignored_types(t): - return t in ["@GDScript", - "@GlobalScope", - "Node", - "AcceptDialog", - "AnimatableBody2D", - "AnimatableBody3D", - "AnimatedSprite2D", - "AnimatedSprite3D", - "AnimationPlayer", - "AnimationTree", - "Area2D", - "Area3D", - "AspectRatioContainer", - "AudioListener2D", - "AudioListener3D", - "AudioStreamPlayer", - "AudioStreamPlayer2D", - "AudioStreamPlayer3D", - "BackBufferCopy", - "BaseButton", - "Bone2D", - "BoneAttachment3D", - "BoxContainer", - "Button", - "Camera2D", - "Camera3D", - "CanvasGroup", - "CanvasItem", - "CanvasLayer", - "CanvasModulate", - "CenterContainer", - "CharacterBody2D", - "CharacterBody3D", - "CheckBox", - "CheckButton", - "CodeEdit", - "CollisionObject2D", - "CollisionObject3D", - "CollisionPolygon2D", - "CollisionPolygon3D", - "CollisionShape2D", - "CollisionShape3D", - "ColorPicker", - "ColorPickerButton", - "ColorRect", - "ConeTwistJoint3D", - "ConfirmationDialog", - "Container", - "Control", - "CPUParticles2D", - "CPUParticles3D", - "CSGBox3D", - "CSGCombiner3D", - "CSGCylinder3D", - "CSGMesh3D", - "CSGPolygon3D", - "CSGPrimitive3D", - "CSGShape3D", - "CSGSphere3D", - "CSGTorus3D", - "DampedSpringJoint2D", - "Decal", - "DirectionalLight2D", - "DirectionalLight3D", - "EditorCommandPalette", - "EditorFileDialog", - "EditorFileSystem", - "EditorInspector", - "EditorInterface", - "EditorPlugin", - "EditorProperty", - "EditorResourcePicker", - "EditorResourcePreview", - "EditorScriptPicker", - "EditorSpinSlider", - "FileDialog", - "FileSystemDock", - "FlowContainer", - "FogVolume", - "Generic6DOFJoint3D", - "GeometryInstance3D", - "GPUParticles2D", - "GPUParticles3D", - "GPUParticlesAttractor3D", - "GPUParticlesAttractorBox3D", - "GPUParticlesAttractorSphere3D", - "GPUParticlesAttractorVectorField3D", - "GPUParticlesCollision3D", - "GPUParticlesCollisionBox3D", - "GPUParticlesCollisionHeightField3D", - "GPUParticlesCollisionSDF3D", - "GPUParticlesCollisionSphere3D", - "GraphEdit", - "GraphNode", - "GridContainer", - "GridMap", - "GrooveJoint2D", - "HBoxContainer", - "HFlowContainer", - "HingeJoint3D", - "HScrollBar", - "HSeparator", - "HSlider", - "HSplitContainer", - "HTTPRequest", - "ImporterMeshInstance3D", - "InstancePlaceholder", - "ItemList", - "Joint2D", - "Joint3D", - "Label", - "Label3D", - "Light2D", - "Light3D", - "LightmapGI", - "LightmapProbe", - "LightOccluder2D", - "Line2D", - "LineEdit", - "LinkButton", - "MarginContainer", - "Marker2D", - "Marker3D", - "MenuBar", - "MenuButton", - "MeshInstance2D", - "MeshInstance3D", - "MissingNode", - "MultiMeshInstance2D", - "MultiMeshInstance3D", - "MultiplayerSpawner", - "MultiplayerSynchronizer", - "NavigationAgent2D", - "NavigationAgent3D", - "NavigationLink2D", - "NavigationLink3D", - "NavigationObstacle2D", - "NavigationObstacle3D", - "NavigationRegion2D", - "NavigationRegion3D", - "NinePatchRect", - "Node2D", - "Node3D", - "OccluderInstance3D", - "OmniLight3D", - "OpenXRHand", - "OptionButton", - "Panel", - "PanelContainer", - "ParallaxBackground", - "ParallaxLayer", - "Path2D", - "Path3D", - "PathFollow2D", - "PathFollow3D", - "PhysicalBone2D", - "PhysicalBone3D", - "PhysicsBody2D", - "PhysicsBody3D", - "PinJoint2D", - "PinJoint3D", - "PointLight2D", - "Polygon2D", - "Popup", - "PopupMenu", - "PopupPanel", - "ProgressBar", - "Range", - "RayCast2D", - "RayCast3D", - "ReferenceRect", - "ReflectionProbe", - "RemoteTransform2D", - "RemoteTransform3D", - "ResourcePreloader", - "RichTextLabel", - "RigidBody2D", - "RigidBody3D", - "RootMotionView", - "ScriptCreateDialog", - "ScriptEditor", - "ScriptEditorBase", - "ScrollBar", - "ScrollContainer", - "Separator", - "ShaderGlobalsOverride", - "ShapeCast2D", - "ShapeCast3D", - "Skeleton2D", - "Skeleton3D", - "SkeletonIK3D", - "Slider", - "SliderJoint3D", - "SoftBody3D", - "SpinBox", - "SplitContainer", - "SpotLight3D", - "SpringArm3D", - "Sprite2D", - "Sprite3D", - "SpriteBase3D", - "StaticBody2D", - "StaticBody3D", - "SubViewport", - "SubViewportContainer", - "TabBar", - "TabContainer", - "TextEdit", - "TextureButton", - "TextureProgressBar", - "TextureRect", - "TileMap", - "Timer", - "TouchScreenButton", - "Tree", - "VBoxContainer", - "VehicleBody3D", - "VehicleWheel3D", - "VFlowContainer", - "VideoStreamPlayer", - "Viewport", - "VisibleOnScreenEnabler2D", - "VisibleOnScreenEnabler3D", - "VisibleOnScreenNotifier2D", - "VisibleOnScreenNotifier3D", - "VisualInstance3D", - "VoxelGI", - "VScrollBar", - "VSeparator", - "VSlider", - "VSplitContainer", - "Window", - "WorldEnvironment", - "XRAnchor3D", - "XRCamera3D", - "XRController3D", - "XRNode3D", - "XROrigin3D", - "Resource", - "AnimatedTexture", - "Animation", - "AnimationLibrary", - "AnimationNode", - "AnimationNodeAdd2", - "AnimationNodeAdd3", - "AnimationNodeAnimation", - "AnimationNodeBlend2", - "AnimationNodeBlend3", - "AnimationNodeBlendSpace1D", - "AnimationNodeBlendSpace2D", - "AnimationNodeBlendTree", - "AnimationNodeOneShot", - "AnimationNodeOutput", - "AnimationNodeStateMachine", - "AnimationNodeStateMachinePlayback", - "AnimationNodeStateMachineTransition", - "AnimationNodeSync", - "AnimationNodeTimeScale", - "AnimationNodeTimeSeek", - "AnimationNodeTransition", - "AnimationRootNode", - "ArrayMesh", - "ArrayOccluder3D", - "AtlasTexture", - "AudioBusLayout", - "AudioEffect", - "AudioEffectAmplify", - "AudioEffectBandLimitFilter", - "AudioEffectBandPassFilter", - "AudioEffectCapture", - "AudioEffectChorus", - "AudioEffectCompressor", - "AudioEffectDelay", - "AudioEffectDistortion", - "AudioEffectEQ", - "AudioEffectEQ10", - "AudioEffectEQ21", - "AudioEffectEQ6", - "AudioEffectFilter", - "AudioEffectHighPassFilter", - "AudioEffectHighShelfFilter", - "AudioEffectLimiter", - "AudioEffectLowPassFilter", - "AudioEffectLowShelfFilter", - "AudioEffectNotchFilter", - "AudioEffectPanner", - "AudioEffectPhaser", - "AudioEffectPitchShift", - "AudioEffectRecord", - "AudioEffectReverb", - "AudioEffectSpectrumAnalyzer", - "AudioEffectStereoEnhance", - "AudioStream", - "AudioStreamGenerator", - "AudioStreamMicrophone", - "AudioStreamMP3", - "AudioStreamOggVorbis", - "AudioStreamPolyphonic", - "AudioStreamRandomizer", - "AudioStreamWAV", - "BaseMaterial3D", - "BitMap", - "BoneMap", - "BoxMesh", - "BoxOccluder3D", - "BoxShape3D", - "ButtonGroup", - "CameraAttributes", - "CameraAttributesPhysical", - "CameraAttributesPractical", - "CameraTexture", - "CanvasItemMaterial", - "CanvasTexture", - "CapsuleMesh", - "CapsuleShape2D", - "CapsuleShape3D", - "CircleShape2D", - "CodeHighlighter", - "CompressedCubemap", - "CompressedCubemapArray", - "CompressedTexture2D", - "CompressedTexture2DArray", - "CompressedTexture3D", - "CompressedTextureLayered", - "ConcavePolygonShape2D", - "ConcavePolygonShape3D", - "ConvexPolygonShape2D", - "ConvexPolygonShape3D", - "CryptoKey", - "CSharpScript", - "Cubemap", - "CubemapArray", - "Curve", - "Curve2D", - "Curve3D", - "CurveTexture", - "CurveXYZTexture", - "CylinderMesh", - "CylinderShape3D", - "EditorNode3DGizmoPlugin", - "EditorSettings", - "EditorSyntaxHighlighter", - "Environment", - "FastNoiseLite", - "FogMaterial", - "Font", - "FontFile", - "FontVariation", - "GDExtension", - "GDScript", - "GLTFAccessor", - "GLTFAnimation", - "GLTFBufferView", - "GLTFCamera", - "GLTFDocument", - "GLTFDocumentExtension", - "GLTFDocumentExtensionConvertImporterMesh", - "GLTFLight", - "GLTFMesh", - "GLTFNode", - "GLTFSkeleton", - "GLTFSkin", - "GLTFSpecGloss", - "GLTFState", - "GLTFTexture", - "GLTFTextureSampler", - "Gradient", - "GradientTexture1D", - "GradientTexture2D", - "HeightMapShape3D", - "Image", - "ImageTexture", - "ImageTexture3D", - "ImageTextureLayered", - "ImmediateMesh", - "ImporterMesh", - "InputEvent", - "InputEventAction", - "InputEventFromWindow", - "InputEventGesture", - "InputEventJoypadButton", - "InputEventJoypadMotion", - "InputEventKey", - "InputEventMagnifyGesture", - "InputEventMIDI", - "InputEventMouse", - "InputEventMouseButton", - "InputEventMouseMotion", - "InputEventPanGesture", - "InputEventScreenDrag", - "InputEventScreenTouch", - "InputEventShortcut", - "InputEventWithModifiers", - "JSON", - "LabelSettings", - "LightmapGIData", - "Material", - "Mesh", - "MeshLibrary", - "MeshTexture", - "MissingResource", - "MultiMesh", - "NavigationMesh", - "NavigationPolygon", - "Noise", - "NoiseTexture2D", - "Occluder3D", - "OccluderPolygon2D", - "OggPacketSequence", - "OpenXRAction", - "OpenXRActionMap", - "OpenXRActionSet", - "OpenXRInteractionProfile", - "OpenXRIPBinding", - "OptimizedTranslation", - "ORMMaterial3D", - "PackedDataContainer", - "PackedScene", - "PanoramaSkyMaterial", - "ParticleProcessMaterial", - "PhysicalSkyMaterial", - "PhysicsMaterial", - "PlaceholderCubemap", - "PlaceholderCubemapArray", - "PlaceholderMaterial", - "PlaceholderMesh", - "PlaceholderTexture2D", - "PlaceholderTexture2DArray", - "PlaceholderTexture3D", - "PlaceholderTextureLayered", - "PlaneMesh", - "PointMesh", - "PolygonOccluder3D", - "PolygonPathFinder", - "PortableCompressedTexture2D", - "PrimitiveMesh", - "PrismMesh", - "ProceduralSkyMaterial", - "QuadMesh", - "QuadOccluder3D", - "RDShaderFile", - "RDShaderSPIRV", - "RectangleShape2D", - "RibbonTrailMesh", - "RichTextEffect", - "SceneReplicationConfig", - "Script", - "ScriptExtension", - "SegmentShape2D", - "SeparationRayShape2D", - "SeparationRayShape3D", - "Shader", - "ShaderInclude", - "ShaderMaterial", - "Shape2D", - "Shape3D", - "Shortcut", - "SkeletonModification2D", - "SkeletonModification2DCCDIK", - "SkeletonModification2DFABRIK", - "SkeletonModification2DJiggle", - "SkeletonModification2DLookAt", - "SkeletonModification2DPhysicalBones", - "SkeletonModification2DStackHolder", - "SkeletonModification2DTwoBoneIK", - "SkeletonModificationStack2D", - "SkeletonProfile", - "SkeletonProfileHumanoid", - "Skin", - "Sky", - "SphereMesh", - "SphereOccluder3D", - "SphereShape3D", - "SpriteFrames", - "StandardMaterial3D", - "StyleBox", - "StyleBoxEmpty", - "StyleBoxFlat", - "StyleBoxLine", - "StyleBoxTexture", - "SyntaxHighlighter", - "SystemFont", - "TextMesh", - "Texture", - "Texture2D", - "Texture2DArray", - "Texture3D", - "TextureLayered", - "Theme", - "TileMapPattern", - "TileSet", - "TileSetAtlasSource", - "TileSetScenesCollectionSource", - "TileSetSource", - "TorusMesh", - "Translation", - "TubeTrailMesh", - "VideoStream", - "VideoStreamPlayback", - "VideoStreamTheora", - "ViewportTexture", - "VisualShader", - "VisualShaderNode", - "VisualShaderNodeBillboard", - "VisualShaderNodeBooleanConstant", - "VisualShaderNodeBooleanParameter", - "VisualShaderNodeClamp", - "VisualShaderNodeColorConstant", - "VisualShaderNodeColorFunc", - "VisualShaderNodeColorOp", - "VisualShaderNodeColorParameter", - "VisualShaderNodeComment", - "VisualShaderNodeCompare", - "VisualShaderNodeConstant", - "VisualShaderNodeCubemap", - "VisualShaderNodeCubemapParameter", - "VisualShaderNodeCurveTexture", - "VisualShaderNodeCurveXYZTexture", - "VisualShaderNodeCustom", - "VisualShaderNodeDerivativeFunc", - "VisualShaderNodeDeterminant", - "VisualShaderNodeDistanceFade", - "VisualShaderNodeDotProduct", - "VisualShaderNodeExpression", - "VisualShaderNodeFaceForward", - "VisualShaderNodeFloatConstant", - "VisualShaderNodeFloatFunc", - "VisualShaderNodeFloatOp", - "VisualShaderNodeFloatParameter", - "VisualShaderNodeFresnel", - "VisualShaderNodeGlobalExpression", - "VisualShaderNodeGroupBase", - "VisualShaderNodeIf", - "VisualShaderNodeInput", - "VisualShaderNodeIntConstant", - "VisualShaderNodeIntFunc", - "VisualShaderNodeIntOp", - "VisualShaderNodeIntParameter", - "VisualShaderNodeIs", - "VisualShaderNodeLinearSceneDepth", - "VisualShaderNodeMix", - "VisualShaderNodeMultiplyAdd", - "VisualShaderNodeOuterProduct", - "VisualShaderNodeOutput", - "VisualShaderNodeParameter", - "VisualShaderNodeParameterRef", - "VisualShaderNodeParticleAccelerator", - "VisualShaderNodeParticleBoxEmitter", - "VisualShaderNodeParticleConeVelocity", - "VisualShaderNodeParticleEmit", - "VisualShaderNodeParticleEmitter", - "VisualShaderNodeParticleMeshEmitter", - "VisualShaderNodeParticleMultiplyByAxisAngle", - "VisualShaderNodeParticleOutput", - "VisualShaderNodeParticleRandomness", - "VisualShaderNodeParticleRingEmitter", - "VisualShaderNodeParticleSphereEmitter", - "VisualShaderNodeProximityFade", - "VisualShaderNodeRandomRange", - "VisualShaderNodeRemap", - "VisualShaderNodeResizableBase", - "VisualShaderNodeSample3D", - "VisualShaderNodeScreenUVToSDF", - "VisualShaderNodeSDFRaymarch", - "VisualShaderNodeSDFToScreenUV", - "VisualShaderNodeSmoothStep", - "VisualShaderNodeStep", - "VisualShaderNodeSwitch", - "VisualShaderNodeTexture", - "VisualShaderNodeTexture2DArray", - "VisualShaderNodeTexture2DArrayParameter", - "VisualShaderNodeTexture2DParameter", - "VisualShaderNodeTexture3D", - "VisualShaderNodeTexture3DParameter", - "VisualShaderNodeTextureParameter", - "VisualShaderNodeTextureParameterTriplanar", - "VisualShaderNodeTextureSDF", - "VisualShaderNodeTextureSDFNormal", - "VisualShaderNodeTransformCompose", - "VisualShaderNodeTransformConstant", - "VisualShaderNodeTransformDecompose", - "VisualShaderNodeTransformFunc", - "VisualShaderNodeTransformOp", - "VisualShaderNodeTransformParameter", - "VisualShaderNodeTransformVecMult", - "VisualShaderNodeUIntConstant", - "VisualShaderNodeUIntFunc", - "VisualShaderNodeUIntOp", - "VisualShaderNodeUIntParameter", - "VisualShaderNodeUVFunc", - "VisualShaderNodeUVPolarCoord", - "VisualShaderNodeVarying", - "VisualShaderNodeVaryingGetter", - "VisualShaderNodeVaryingSetter", - "VisualShaderNodeVec2Constant", - "VisualShaderNodeVec2Parameter", - "VisualShaderNodeVec3Constant", - "VisualShaderNodeVec3Parameter", - "VisualShaderNodeVec4Constant", - "VisualShaderNodeVec4Parameter", - "VisualShaderNodeVectorBase", - "VisualShaderNodeVectorCompose", - "VisualShaderNodeVectorDecompose", - "VisualShaderNodeVectorDistance", - "VisualShaderNodeVectorFunc", - "VisualShaderNodeVectorLen", - "VisualShaderNodeVectorOp", - "VisualShaderNodeVectorRefract", - "VoxelGIData", - "World2D", - "World3D", - "WorldBoundaryShape2D", - "WorldBoundaryShape3D", - "X509Certificate", - "Object", - "AESContext", - "AnimationTrackEditPlugin", - "AStar2D", - "AStar3D", - "AStarGrid2D", - "AudioEffectInstance", - "AudioEffectSpectrumAnalyzerInstance", - "AudioServer", - "AudioStreamGeneratorPlayback", - "AudioStreamPlayback", - "AudioStreamPlaybackOggVorbis", - "AudioStreamPlaybackPolyphonic", - "AudioStreamPlaybackResampled", - "CallbackTweener", - "CameraFeed", - "CameraServer", - "CharFXTransform", - "ClassDB", - "ConfigFile", - "Crypto", - "DirAccess", - "DisplayServer", - "DTLSServer", - "EditorDebuggerPlugin", - "EditorDebuggerSession", - "EditorExportPlatform", - "EditorExportPlugin", - "EditorFeatureProfile", - "EditorFileSystemDirectory", - "EditorFileSystemImportFormatSupportQuery", - "EditorImportPlugin", - "EditorInspectorPlugin", - "EditorNode3DGizmo", - "EditorPaths", - "EditorResourceConversionPlugin", - "EditorResourcePreviewGenerator", - "EditorSceneFormatImporter", - "EditorSceneFormatImporterBlend", - "EditorSceneFormatImporterFBX", - "EditorSceneFormatImporterGLTF", - "EditorScenePostImport", - "EditorScenePostImportPlugin", - "EditorScript", - "EditorSelection", - "EditorTranslationParserPlugin", - "EditorUndoRedoManager", - "EditorVCSInterface", - "EncodedObjectAsID", - "ENetConnection", - "ENetMultiplayerPeer", - "ENetPacketPeer", - "Engine", - "EngineDebugger", - "EngineProfiler", - "Expression", - "FileAccess", - "GDExtensionManager", - "Geometry2D", - "Geometry3D", - "GodotSharp", - "HashingContext", - "HMACContext", - "HTTPClient", - "ImageFormatLoader", - "ImageFormatLoaderExtension", - "Input", - "InputMap", - "IntervalTweener", - "IP", - "JavaClass", - "JavaClassWrapper", - "JavaScriptBridge", - "JavaScriptObject", - "JNISingleton", - "JSONRPC", - "KinematicCollision2D", - "KinematicCollision3D", - "Lightmapper", - "LightmapperRD", - "MainLoop", - "Marshalls", - "MeshDataTool", - "MethodTweener", - "MobileVRInterface", - "MovieWriter", - "MultiplayerAPI", - "MultiplayerAPIExtension", - "MultiplayerPeer", - "MultiplayerPeerExtension", - "Mutex", - "NavigationMeshGenerator", - "NavigationPathQueryParameters2D", - "NavigationPathQueryParameters3D", - "NavigationPathQueryResult2D", - "NavigationPathQueryResult3D", - "NavigationServer2D", - "NavigationServer3D", - "Node", - "Node3DGizmo", - "OfflineMultiplayerPeer", - "OggPacketSequencePlayback", - "OpenXRInterface", - "OS", - "PackedDataContainerRef", - "PacketPeer", - "PacketPeerDTLS", - "PacketPeerExtension", - "PacketPeerStream", - "PacketPeerUDP", - "PCKPacker", - "Performance", - "PhysicsDirectBodyState2D", - "PhysicsDirectBodyState2DExtension", - "PhysicsDirectBodyState3D", - "PhysicsDirectBodyState3DExtension", - "PhysicsDirectSpaceState2D", - "PhysicsDirectSpaceState2DExtension", - "PhysicsDirectSpaceState3D", - "PhysicsDirectSpaceState3DExtension", - "PhysicsPointQueryParameters2D", - "PhysicsPointQueryParameters3D", - "PhysicsRayQueryParameters2D", - "PhysicsRayQueryParameters3D", - "PhysicsServer2D", - "PhysicsServer2DExtension", - "PhysicsServer2DManager", - "PhysicsServer3D", - "PhysicsServer3DExtension", - "PhysicsServer3DManager", - "PhysicsServer3DRenderingServerHandler", - "PhysicsShapeQueryParameters2D", - "PhysicsShapeQueryParameters3D", - "PhysicsTestMotionParameters2D", - "PhysicsTestMotionParameters3D", - "PhysicsTestMotionResult2D", - "PhysicsTestMotionResult3D", - "ProjectSettings", - "PropertyTweener", - "RandomNumberGenerator", - "RDAttachmentFormat", - "RDFramebufferPass", - "RDPipelineColorBlendState", - "RDPipelineColorBlendStateAttachment", - "RDPipelineDepthStencilState", - "RDPipelineMultisampleState", - "RDPipelineRasterizationState", - "RDPipelineSpecializationConstant", - "RDSamplerState", - "RDShaderSource", - "RDTextureFormat", - "RDTextureView", - "RDUniform", - "RDVertexAttribute", - "RefCounted", - "RegEx", - "RegExMatch", - "RenderingDevice", - "RenderingServer", - "Resource", - "ResourceFormatLoader", - "ResourceFormatSaver", - "ResourceImporter", - "ResourceLoader", - "ResourceSaver", - "ResourceUID", - "SceneMultiplayer", - "SceneState", - "SceneTree", - "SceneTreeTimer", - "ScriptLanguage", - "ScriptLanguageExtension", - "Semaphore", - "SkinReference", - "StreamPeer", - "StreamPeerBuffer", - "StreamPeerExtension", - "StreamPeerGZIP", - "StreamPeerTCP", - "StreamPeerTLS", - "SurfaceTool", - "TCPServer", - "TextLine", - "TextParagraph", - "TextServer", - "TextServerAdvanced", - "TextServerDummy", - "TextServerExtension", - "TextServerFallback", - "TextServerManager", - "ThemeDB", - "Thread", - "TileData", - "Time", - "TLSOptions", - "TranslationServer", - "TreeItem", - "TriangleMesh", - "Tween", - "Tweener", - "UDPServer", - "UndoRedo", - "UPNP", - "UPNPDevice", - "WeakRef", - "WebRTCDataChannel", - "WebRTCDataChannelExtension", - "WebRTCMultiplayerPeer", - "WebRTCPeerConnection", - "WebRTCPeerConnectionExtension", - "WebSocketMultiplayerPeer", - "WebSocketPeer", - "WebXRInterface", - "WorkerThreadPool", - "XMLParser", - "XRInterface", - "XRInterfaceExtension", - "XRPose", - "XRPositionalTracker", - "XRServer", - "ZIPPacker", - "ZIPReader", - "AABB", - "Array", - "Basis", - "bool", - "Callable", - "Color", - "Dictionary", - "float", - "int", - "NodePath", - "Object", - "PackedByteArray", - "PackedColorArray", - "PackedFloat32Array", - "PackedFloat64Array", - "PackedInt32Array", - "PackedInt64Array", - "PackedStringArray", - "PackedVector2Array", - "PackedVector3Array", - "Plane", - "Projection", - "Quaternion", - "Rect2", - "Rect2i", - "RID", - "Signal", - "String", - "StringName", - "Transform2D", - "Transform3D", - "Variant", - "Vector2", - "Vector2i", - "Vector3", - "Vector3i", - "Vector4", - "Vector4i" - ] - - -# Example usage -find_circular_dependencies("C:\\Workspace\\TL2\\gd_client\\scripts") diff --git a/circular-dependency-checker/go.mod b/circular-dependency-checker/go.mod new file mode 100644 index 0000000..fd0bed7 --- /dev/null +++ b/circular-dependency-checker/go.mod @@ -0,0 +1,3 @@ +module github.com/tiennm99/circular-dependency-checker + +go 1.21 diff --git a/circular-dependency-checker/go.sum b/circular-dependency-checker/go.sum new file mode 100644 index 0000000..8d8623a --- /dev/null +++ b/circular-dependency-checker/go.sum @@ -0,0 +1,2 @@ +github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= +github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= diff --git a/circular-dependency-checker/main.go b/circular-dependency-checker/main.go new file mode 100644 index 0000000..0b02ff0 --- /dev/null +++ b/circular-dependency-checker/main.go @@ -0,0 +1,1044 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" +) + +var ignoredTypes = []string{ + "@GDScript", + "@GlobalScope", + "Node", + "AcceptDialog", + "AnimatableBody2D", + "AnimatableBody3D", + "AnimatedSprite2D", + "AnimatedSprite3D", + "AnimationPlayer", + "AnimationTree", + "Area2D", + "Area3D", + "AspectRatioContainer", + "AudioListener2D", + "AudioListener3D", + "AudioStreamPlayer", + "AudioStreamPlayer2D", + "AudioStreamPlayer3D", + "BackBufferCopy", + "BaseButton", + "Bone2D", + "BoneAttachment3D", + "BoxContainer", + "Button", + "Camera2D", + "Camera3D", + "CanvasGroup", + "CanvasItem", + "CanvasLayer", + "CanvasModulate", + "CenterContainer", + "CharacterBody2D", + "CharacterBody3D", + "CheckBox", + "CheckButton", + "CodeEdit", + "CollisionObject2D", + "CollisionObject3D", + "CollisionPolygon2D", + "CollisionPolygon3D", + "CollisionShape2D", + "CollisionShape3D", + "ColorPicker", + "ColorPickerButton", + "ColorRect", + "ConeTwistJoint3D", + "ConfirmationDialog", + "Container", + "Control", + "CPUParticles2D", + "CPUParticles3D", + "CSGBox3D", + "CSGCombiner3D", + "CSGCylinder3D", + "CSGMesh3D", + "CSGPolygon3D", + "CSGPrimitive3D", + "CSGShape3D", + "CSGSphere3D", + "CSGTorus3D", + "DampedSpringJoint2D", + "Decal", + "DirectionalLight2D", + "DirectionalLight3D", + "EditorCommandPalette", + "EditorFileDialog", + "EditorFileSystem", + "EditorInspector", + "EditorInterface", + "EditorPlugin", + "EditorProperty", + "EditorResourcePicker", + "EditorResourcePreview", + "EditorScriptPicker", + "EditorSpinSlider", + "FileDialog", + "FileSystemDock", + "FlowContainer", + "FogVolume", + "Generic6DOFJoint3D", + "GeometryInstance3D", + "GPUParticles2D", + "GPUParticles3D", + "GPUParticlesAttractor3D", + "GPUParticlesAttractorBox3D", + "GPUParticlesAttractorSphere3D", + "GPUParticlesAttractorVectorField3D", + "GPUParticlesCollision3D", + "GPUParticlesCollisionBox3D", + "GPUParticlesCollisionHeightField3D", + "GPUParticlesCollisionSDF3D", + "GPUParticlesCollisionSphere3D", + "GraphEdit", + "GraphNode", + "GridContainer", + "GridMap", + "GrooveJoint2D", + "HBoxContainer", + "HFlowContainer", + "HingeJoint3D", + "HScrollBar", + "HSeparator", + "HSlider", + "HSplitContainer", + "HTTPRequest", + "ImporterMeshInstance3D", + "InstancePlaceholder", + "ItemList", + "Joint2D", + "Joint3D", + "Label", + "Label3D", + "Light2D", + "Light3D", + "LightmapGI", + "LightmapProbe", + "LightOccluder2D", + "Line2D", + "LineEdit", + "LinkButton", + "MarginContainer", + "Marker2D", + "Marker3D", + "MenuBar", + "MenuButton", + "MeshInstance2D", + "MeshInstance3D", + "MissingNode", + "MultiMeshInstance2D", + "MultiMeshInstance3D", + "MultiplayerSpawner", + "MultiplayerSynchronizer", + "NavigationAgent2D", + "NavigationAgent3D", + "NavigationLink2D", + "NavigationLink3D", + "NavigationObstacle2D", + "NavigationObstacle3D", + "NavigationRegion2D", + "NavigationRegion3D", + "NinePatchRect", + "Node2D", + "Node3D", + "OccluderInstance3D", + "OmniLight3D", + "OpenXRHand", + "OptionButton", + "Panel", + "PanelContainer", + "ParallaxBackground", + "ParallaxLayer", + "Path2D", + "Path3D", + "PathFollow2D", + "PathFollow3D", + "PhysicalBone2D", + "PhysicalBone3D", + "PhysicsBody2D", + "PhysicsBody3D", + "PinJoint2D", + "PinJoint3D", + "PointLight2D", + "Polygon2D", + "Popup", + "PopupMenu", + "PopupPanel", + "ProgressBar", + "Range", + "RayCast2D", + "RayCast3D", + "ReferenceRect", + "ReflectionProbe", + "RemoteTransform2D", + "RemoteTransform3D", + "ResourcePreloader", + "RichTextLabel", + "RigidBody2D", + "RigidBody3D", + "RootMotionView", + "ScriptCreateDialog", + "ScriptEditor", + "ScriptEditorBase", + "ScrollBar", + "ScrollContainer", + "Separator", + "ShaderGlobalsOverride", + "ShapeCast2D", + "ShapeCast3D", + "Skeleton2D", + "Skeleton3D", + "SkeletonIK3D", + "Slider", + "SliderJoint3D", + "SoftBody3D", + "SpinBox", + "SplitContainer", + "SpotLight3D", + "SpringArm3D", + "Sprite2D", + "Sprite3D", + "SpriteBase3D", + "StaticBody2D", + "StaticBody3D", + "SubViewport", + "SubViewportContainer", + "TabBar", + "TabContainer", + "TextEdit", + "TextureButton", + "TextureProgressBar", + "TextureRect", + "TileMap", + "Timer", + "TouchScreenButton", + "Tree", + "VBoxContainer", + "VehicleBody3D", + "VehicleWheel3D", + "VFlowContainer", + "VideoStreamPlayer", + "Viewport", + "VisibleOnScreenEnabler2D", + "VisibleOnScreenEnabler3D", + "VisibleOnScreenNotifier2D", + "VisibleOnScreenNotifier3D", + "VisualInstance3D", + "VoxelGI", + "VScrollBar", + "VSeparator", + "VSlider", + "VSplitContainer", + "Window", + "WorldEnvironment", + "XRAnchor3D", + "XRCamera3D", + "XRController3D", + "XRNode3D", + "XROrigin3D", + "Resource", + "AnimatedTexture", + "Animation", + "AnimationLibrary", + "AnimationNode", + "AnimationNodeAdd2", + "AnimationNodeAdd3", + "AnimationNodeAnimation", + "AnimationNodeBlend2", + "AnimationNodeBlend3", + "AnimationNodeBlendSpace1D", + "AnimationNodeBlendSpace2D", + "AnimationNodeBlendTree", + "AnimationNodeOneShot", + "AnimationNodeOutput", + "AnimationNodeStateMachine", + "AnimationNodeStateMachinePlayback", + "AnimationNodeStateMachineTransition", + "AnimationNodeSync", + "AnimationNodeTimeScale", + "AnimationNodeTimeSeek", + "AnimationNodeTransition", + "AnimationRootNode", + "ArrayMesh", + "ArrayOccluder3D", + "AtlasTexture", + "AudioBusLayout", + "AudioEffect", + "AudioEffectAmplify", + "AudioEffectBandLimitFilter", + "AudioEffectBandPassFilter", + "AudioEffectCapture", + "AudioEffectChorus", + "AudioEffectCompressor", + "AudioEffectDelay", + "AudioEffectDistortion", + "AudioEffectEQ", + "AudioEffectEQ10", + "AudioEffectEQ21", + "AudioEffectEQ6", + "AudioEffectFilter", + "AudioEffectHighPassFilter", + "AudioEffectHighShelfFilter", + "AudioEffectLimiter", + "AudioEffectLowPassFilter", + "AudioEffectLowShelfFilter", + "AudioEffectNotchFilter", + "AudioEffectPanner", + "AudioEffectPhaser", + "AudioEffectPitchShift", + "AudioEffectRecord", + "AudioEffectReverb", + "AudioEffectSpectrumAnalyzer", + "AudioEffectStereoEnhance", + "AudioStream", + "AudioStreamGenerator", + "AudioStreamMicrophone", + "AudioStreamMP3", + "AudioStreamOggVorbis", + "AudioStreamPolyphonic", + "AudioStreamRandomizer", + "AudioStreamWAV", + "BaseMaterial3D", + "BitMap", + "BoneMap", + "BoxMesh", + "BoxOccluder3D", + "BoxShape3D", + "ButtonGroup", + "CameraAttributes", + "CameraAttributesPhysical", + "CameraAttributesPractical", + "CameraTexture", + "CanvasItemMaterial", + "CanvasTexture", + "CapsuleMesh", + "CapsuleShape2D", + "CapsuleShape3D", + "CircleShape2D", + "CodeHighlighter", + "CompressedCubemap", + "CompressedCubemapArray", + "CompressedTexture2D", + "CompressedTexture2DArray", + "CompressedTexture3D", + "CompressedTextureLayered", + "ConcavePolygonShape2D", + "ConcavePolygonShape3D", + "ConvexPolygonShape2D", + "ConvexPolygonShape3D", + "CryptoKey", + "CSharpScript", + "Cubemap", + "CubemapArray", + "Curve", + "Curve2D", + "Curve3D", + "CurveTexture", + "CurveXYZTexture", + "CylinderMesh", + "CylinderShape3D", + "EditorNode3DGizmoPlugin", + "EditorSettings", + "EditorSyntaxHighlighter", + "Environment", + "FastNoiseLite", + "FogMaterial", + "Font", + "FontFile", + "FontVariation", + "GDExtension", + "GDScript", + "GLTFAccessor", + "GLTFAnimation", + "GLTFBufferView", + "GLTFCamera", + "GLTFDocument", + "GLTFDocumentExtension", + "GLTFDocumentExtensionConvertImporterMesh", + "GLTFLight", + "GLTFMesh", + "GLTFNode", + "GLTFSkeleton", + "GLTFSkin", + "GLTFSpecGloss", + "GLTFState", + "GLTFTexture", + "GLTFTextureSampler", + "Gradient", + "GradientTexture1D", + "GradientTexture2D", + "HeightMapShape3D", + "Image", + "ImageTexture", + "ImageTexture3D", + "ImageTextureLayered", + "ImmediateMesh", + "ImporterMesh", + "InputEvent", + "InputEventAction", + "InputEventFromWindow", + "InputEventGesture", + "InputEventJoypadButton", + "InputEventJoypadMotion", + "InputEventKey", + "InputEventMagnifyGesture", + "InputEventMIDI", + "InputEventMouse", + "InputEventMouseButton", + "InputEventMouseMotion", + "InputEventPanGesture", + "InputEventScreenDrag", + "InputEventScreenTouch", + "InputEventShortcut", + "InputEventWithModifiers", + "JSON", + "LabelSettings", + "LightmapGIData", + "Material", + "Mesh", + "MeshLibrary", + "MeshTexture", + "MissingResource", + "MultiMesh", + "NavigationMesh", + "NavigationPolygon", + "Noise", + "NoiseTexture2D", + "Occluder3D", + "OccluderPolygon2D", + "OggPacketSequence", + "OpenXRAction", + "OpenXRActionMap", + "OpenXRActionSet", + "OpenXRInteractionProfile", + "OpenXRIPBinding", + "OptimizedTranslation", + "ORMMaterial3D", + "PackedDataContainer", + "PackedScene", + "PanoramaSkyMaterial", + "ParticleProcessMaterial", + "PhysicalSkyMaterial", + "PhysicsMaterial", + "PlaceholderCubemap", + "PlaceholderCubemapArray", + "PlaceholderMaterial", + "PlaceholderMesh", + "PlaceholderTexture2D", + "PlaceholderTexture2DArray", + "PlaceholderTexture3D", + "PlaceholderTextureLayered", + "PlaneMesh", + "PointMesh", + "PolygonOccluder3D", + "PolygonPathFinder", + "PortableCompressedTexture2D", + "PrimitiveMesh", + "PrismMesh", + "ProceduralSkyMaterial", + "QuadMesh", + "QuadOccluder3D", + "RDShaderFile", + "RDShaderSPIRV", + "RectangleShape2D", + "RibbonTrailMesh", + "RichTextEffect", + "SceneReplicationConfig", + "Script", + "ScriptExtension", + "SegmentShape2D", + "SeparationRayShape2D", + "SeparationRayShape3D", + "Shader", + "ShaderInclude", + "ShaderMaterial", + "Shape2D", + "Shape3D", + "Shortcut", + "SkeletonModification2D", + "SkeletonModification2DCCDIK", + "SkeletonModification2DFABRIK", + "SkeletonModification2DJiggle", + "SkeletonModification2DLookAt", + "SkeletonModification2DPhysicalBones", + "SkeletonModification2DStackHolder", + "SkeletonModification2DTwoBoneIK", + "SkeletonModificationStack2D", + "SkeletonProfile", + "SkeletonProfileHumanoid", + "Skin", + "Sky", + "SphereMesh", + "SphereOccluder3D", + "SphereShape3D", + "SpriteFrames", + "StandardMaterial3D", + "StyleBox", + "StyleBoxEmpty", + "StyleBoxFlat", + "StyleBoxLine", + "StyleBoxTexture", + "SyntaxHighlighter", + "SystemFont", + "TextMesh", + "Texture", + "Texture2D", + "Texture2DArray", + "Texture3D", + "TextureLayered", + "Theme", + "TileMapPattern", + "TileSet", + "TileSetAtlasSource", + "TileSetScenesCollectionSource", + "TileSetSource", + "TorusMesh", + "Translation", + "TubeTrailMesh", + "VideoStream", + "VideoStreamPlayback", + "VideoStreamTheora", + "ViewportTexture", + "VisualShader", + "VisualShaderNode", + "VisualShaderNodeBillboard", + "VisualShaderNodeBooleanConstant", + "VisualShaderNodeBooleanParameter", + "VisualShaderNodeClamp", + "VisualShaderNodeColorConstant", + "VisualShaderNodeColorFunc", + "VisualShaderNodeColorOp", + "VisualShaderNodeColorParameter", + "VisualShaderNodeComment", + "VisualShaderNodeCompare", + "VisualShaderNodeConstant", + "VisualShaderNodeCubemap", + "VisualShaderNodeCubemapParameter", + "VisualShaderNodeCurveTexture", + "VisualShaderNodeCurveXYZTexture", + "VisualShaderNodeCustom", + "VisualShaderNodeDerivativeFunc", + "VisualShaderNodeDeterminant", + "VisualShaderNodeDistanceFade", + "VisualShaderNodeDotProduct", + "VisualShaderNodeExpression", + "VisualShaderNodeFaceForward", + "VisualShaderNodeFloatConstant", + "VisualShaderNodeFloatFunc", + "VisualShaderNodeFloatOp", + "VisualShaderNodeFloatParameter", + "VisualShaderNodeFresnel", + "VisualShaderNodeGlobalExpression", + "VisualShaderNodeGroupBase", + "VisualShaderNodeIf", + "VisualShaderNodeInput", + "VisualShaderNodeIntConstant", + "VisualShaderNodeIntFunc", + "VisualShaderNodeIntOp", + "VisualShaderNodeIntParameter", + "VisualShaderNodeIs", + "VisualShaderNodeLinearSceneDepth", + "VisualShaderNodeMix", + "VisualShaderNodeMultiplyAdd", + "VisualShaderNodeOuterProduct", + "VisualShaderNodeOutput", + "VisualShaderNodeParameter", + "VisualShaderNodeParameterRef", + "VisualShaderNodeParticleAccelerator", + "VisualShaderNodeParticleBoxEmitter", + "VisualShaderNodeParticleConeVelocity", + "VisualShaderNodeParticleEmit", + "VisualShaderNodeParticleEmitter", + "VisualShaderNodeParticleMeshEmitter", + "VisualShaderNodeParticleMultiplyByAxisAngle", + "VisualShaderNodeParticleOutput", + "VisualShaderNodeParticleRandomness", + "VisualShaderNodeParticleRingEmitter", + "VisualShaderNodeParticleSphereEmitter", + "VisualShaderNodeProximityFade", + "VisualShaderNodeRandomRange", + "VisualShaderNodeRemap", + "VisualShaderNodeResizableBase", + "VisualShaderNodeSample3D", + "VisualShaderNodeScreenUVToSDF", + "VisualShaderNodeSDFRaymarch", + "VisualShaderNodeSDFToScreenUV", + "VisualShaderNodeSmoothStep", + "VisualShaderNodeStep", + "VisualShaderNodeSwitch", + "VisualShaderNodeTexture", + "VisualShaderNodeTexture2DArray", + "VisualShaderNodeTexture2DArrayParameter", + "VisualShaderNodeTexture2DParameter", + "VisualShaderNodeTexture3D", + "VisualShaderNodeTexture3DParameter", + "VisualShaderNodeTextureParameter", + "VisualShaderNodeTextureParameterTriplanar", + "VisualShaderNodeTextureSDF", + "VisualShaderNodeTextureSDFNormal", + "VisualShaderNodeTransformCompose", + "VisualShaderNodeTransformConstant", + "VisualShaderNodeTransformDecompose", + "VisualShaderNodeTransformFunc", + "VisualShaderNodeTransformOp", + "VisualShaderNodeTransformParameter", + "VisualShaderNodeTransformVecMult", + "VisualShaderNodeUIntConstant", + "VisualShaderNodeUIntFunc", + "VisualShaderNodeUIntOp", + "VisualShaderNodeUIntParameter", + "VisualShaderNodeUVFunc", + "VisualShaderNodeUVPolarCoord", + "VisualShaderNodeVarying", + "VisualShaderNodeVaryingGetter", + "VisualShaderNodeVaryingSetter", + "VisualShaderNodeVec2Constant", + "VisualShaderNodeVec2Parameter", + "VisualShaderNodeVec3Constant", + "VisualShaderNodeVec3Parameter", + "VisualShaderNodeVec4Constant", + "VisualShaderNodeVec4Parameter", + "VisualShaderNodeVectorBase", + "VisualShaderNodeVectorCompose", + "VisualShaderNodeVectorDecompose", + "VisualShaderNodeVectorDistance", + "VisualShaderNodeVectorFunc", + "VisualShaderNodeVectorLen", + "VisualShaderNodeVectorOp", + "VisualShaderNodeVectorRefract", + "VoxelGIData", + "World2D", + "World3D", + "WorldBoundaryShape2D", + "WorldBoundaryShape3D", + "X509Certificate", + "Object", + "AESContext", + "AnimationTrackEditPlugin", + "AStar2D", + "AStar3D", + "AStarGrid2D", + "AudioEffectInstance", + "AudioEffectSpectrumAnalyzerInstance", + "AudioServer", + "AudioStreamGeneratorPlayback", + "AudioStreamPlayback", + "AudioStreamPlaybackOggVorbis", + "AudioStreamPlaybackPolyphonic", + "AudioStreamPlaybackResampled", + "CallbackTweener", + "CameraFeed", + "CameraServer", + "CharFXTransform", + "ClassDB", + "ConfigFile", + "Crypto", + "DirAccess", + "DisplayServer", + "DTLSServer", + "EditorDebuggerPlugin", + "EditorDebuggerSession", + "EditorExportPlatform", + "EditorExportPlugin", + "EditorFeatureProfile", + "EditorFileSystemDirectory", + "EditorFileSystemImportFormatSupportQuery", + "EditorImportPlugin", + "EditorInspectorPlugin", + "EditorNode3DGizmo", + "EditorPaths", + "EditorResourceConversionPlugin", + "EditorResourcePreviewGenerator", + "EditorSceneFormatImporter", + "EditorSceneFormatImporterBlend", + "EditorSceneFormatImporterFBX", + "EditorSceneFormatImporterGLTF", + "EditorScenePostImport", + "EditorScenePostImportPlugin", + "EditorScript", + "EditorSelection", + "EditorTranslationParserPlugin", + "EditorUndoRedoManager", + "EditorVCSInterface", + "EncodedObjectAsID", + "ENetConnection", + "ENetMultiplayerPeer", + "ENetPacketPeer", + "Engine", + "EngineDebugger", + "EngineProfiler", + "Expression", + "FileAccess", + "GDExtensionManager", + "Geometry2D", + "Geometry3D", + "GodotSharp", + "HashingContext", + "HMACContext", + "HTTPClient", + "ImageFormatLoader", + "ImageFormatLoaderExtension", + "Input", + "InputMap", + "IntervalTweener", + "IP", + "JavaClass", + "JavaClassWrapper", + "JavaScriptBridge", + "JavaScriptObject", + "JNISingleton", + "JSONRPC", + "KinematicCollision2D", + "KinematicCollision3D", + "Lightmapper", + "LightmapperRD", + "MainLoop", + "Marshalls", + "MeshDataTool", + "MethodTweener", + "MobileVRInterface", + "MovieWriter", + "MultiplayerAPI", + "MultiplayerAPIExtension", + "MultiplayerPeer", + "MultiplayerPeerExtension", + "Mutex", + "NavigationMeshGenerator", + "NavigationPathQueryParameters2D", + "NavigationPathQueryParameters3D", + "NavigationPathQueryResult2D", + "NavigationPathQueryResult3D", + "NavigationServer2D", + "NavigationServer3D", + "Node", + "Node3DGizmo", + "OfflineMultiplayerPeer", + "OggPacketSequencePlayback", + "OpenXRInterface", + "OS", + "PackedDataContainerRef", + "PacketPeer", + "PacketPeerDTLS", + "PacketPeerExtension", + "PacketPeerStream", + "PacketPeerUDP", + "PCKPacker", + "Performance", + "PhysicsDirectBodyState2D", + "PhysicsDirectBodyState2DExtension", + "PhysicsDirectBodyState3D", + "PhysicsDirectBodyState3DExtension", + "PhysicsDirectSpaceState2D", + "PhysicsDirectSpaceState2DExtension", + "PhysicsDirectSpaceState3D", + "PhysicsDirectSpaceState3DExtension", + "PhysicsPointQueryParameters2D", + "PhysicsPointQueryParameters3D", + "PhysicsRayQueryParameters2D", + "PhysicsRayQueryParameters3D", + "PhysicsServer2D", + "PhysicsServer2DExtension", + "PhysicsServer2DManager", + "PhysicsServer3D", + "PhysicsServer3DExtension", + "PhysicsServer3DManager", + "PhysicsServer3DRenderingServerHandler", + "PhysicsShapeQueryParameters2D", + "PhysicsShapeQueryParameters3D", + "PhysicsTestMotionParameters2D", + "PhysicsTestMotionParameters3D", + "PhysicsTestMotionResult2D", + "PhysicsTestMotionResult3D", + "ProjectSettings", + "PropertyTweener", + "RandomNumberGenerator", + "RDAttachmentFormat", + "RDFramebufferPass", + "RDPipelineColorBlendState", + "RDPipelineColorBlendStateAttachment", + "RDPipelineDepthStencilState", + "RDPipelineMultisampleState", + "RDPipelineRasterizationState", + "RDPipelineSpecializationConstant", + "RDSamplerState", + "RDShaderSource", + "RDTextureFormat", + "RDTextureView", + "RDUniform", + "RDVertexAttribute", + "RefCounted", + "RegEx", + "RegExMatch", + "RenderingDevice", + "RenderingServer", + "Resource", + "ResourceFormatLoader", + "ResourceFormatSaver", + "ResourceImporter", + "ResourceLoader", + "ResourceSaver", + "ResourceUID", + "SceneMultiplayer", + "SceneState", + "SceneTree", + "SceneTreeTimer", + "ScriptLanguage", + "ScriptLanguageExtension", + "Semaphore", + "SkinReference", + "StreamPeer", + "StreamPeerBuffer", + "StreamPeerExtension", + "StreamPeerGZIP", + "StreamPeerTCP", + "StreamPeerTLS", + "SurfaceTool", + "TCPServer", + "TextLine", + "TextParagraph", + "TextServer", + "TextServerAdvanced", + "TextServerDummy", + "TextServerExtension", + "TextServerFallback", + "TextServerManager", + "ThemeDB", + "Thread", + "TileData", + "Time", + "TLSOptions", + "TranslationServer", + "TreeItem", + "TriangleMesh", + "Tween", + "Tweener", + "UDPServer", + "UndoRedo", + "UPNP", + "UPNPDevice", + "WeakRef", + "WebRTCDataChannel", + "WebRTCDataChannelExtension", + "WebRTCMultiplayerPeer", + "WebRTCPeerConnection", + "WebRTCPeerConnectionExtension", + "WebSocketMultiplayerPeer", + "WebSocketPeer", + "WebXRInterface", + "WorkerThreadPool", + "XMLParser", + "XRInterface", + "XRInterfaceExtension", + "XRPose", + "XRPositionalTracker", + "XRServer", + "ZIPPacker", + "ZIPReader", + "AABB", + "Array", + "Basis", + "bool", + "Callable", + "Color", + "Dictionary", + "float", + "int", + "NodePath", + "Object", + "PackedByteArray", + "PackedColorArray", + "PackedFloat32Array", + "PackedFloat64Array", + "PackedInt32Array", + "PackedInt64Array", + "PackedStringArray", + "PackedVector2Array", + "PackedVector3Array", + "Plane", + "Projection", + "Quaternion", + "Rect2", + "Rect2i", + "RID", + "Signal", + "String", + "StringName", + "Transform2D", + "Transform3D", + "Variant", + "Vector2", + "Vector2i", + "Vector3", + "Vector3i", + "Vector4", + "Vector4i", +} + +// isIgnoredTypes checks if a type should be ignored +func isIgnoredTypes(t string) bool { + for _, ignored := range ignoredTypes { + if t == ignored { + return true + } + } + return false +} + +// Dependency represents a class dependency +type Dependency struct { + Class string + DependsOn string +} + +// buildClassGraph builds a list of class dependencies +func buildClassGraph(directory string) ([]Dependency, error) { + var dependencies []Dependency + + // Find all .gd files in the directory + err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.IsDir() && strings.HasSuffix(info.Name(), ".gd") { + contents, err := os.ReadFile(path) + if err != nil { + return err + } + + // Find the class name in the file + classRegex := regexp.MustCompile(`^class_name\s+(\w+)`) + classMatch := classRegex.FindStringSubmatch(string(contents)) + if len(classMatch) < 2 { + return nil + } + + className := classMatch[1] + + // Find dependencies using various patterns + depPatterns := []*regexp.Regexp{ + regexp.MustCompile(`^\s*extends\s+(\w+)`), + regexp.MustCompile(`^.*:\s*(\w+).*\n`), + regexp.MustCompile(`^.*->\s*(\w+).*\n`), + regexp.MustCompile(`^.*Array\[(\w+)].*\n`), + } + + for _, pattern := range depPatterns { + matches := pattern.FindAllStringSubmatch(string(contents), -1) + for _, match := range matches { + if len(match) < 2 { + continue + } + depName := match[1] + + if isIgnoredTypes(depName) || depName == className { + continue + } + + dependencies = append(dependencies, Dependency{ + Class: className, + DependsOn: depName, + }) + } + } + } + return nil + }) + + if err != nil { + return nil, err + } + + return dependencies, nil +} + +// findCircularDependencies finds and prints circular dependencies +func findCircularDependencies(directory string) error { + dependencies, err := buildClassGraph(directory) + if err != nil { + return err + } + + fmt.Println("Circular dependencies found:") + + // Build adjacency list + adjList := make(map[string][]string) + allClasses := make(map[string]bool) + + for _, dep := range dependencies { + adjList[dep.Class] = append(adjList[dep.Class], dep.DependsOn) + allClasses[dep.Class] = true + allClasses[dep.DependsOn] = true + } + + // Check for cycles using DFS + visited := make(map[string]bool) + recursionStack := make(map[string]bool) + + var dfs func(string, []string) bool + dfs = func(vertex string, path []string) bool { + visited[vertex] = true + recursionStack[vertex] = true + path = append(path, vertex) + + for _, neighbor := range adjList[vertex] { + if !visited[neighbor] { + if dfs(neighbor, path) { + return true + } + } else if recursionStack[neighbor] { + // Found a cycle + cycleStart := -1 + for i, node := range path { + if node == neighbor { + cycleStart = i + break + } + } + + if cycleStart >= 0 { + cycle := path[cycleStart:] + fmt.Printf("Cycle detected: %s\n", strings.Join(cycle, " -> ")) + } + return true + } + } + + recursionStack[vertex] = false + return false + } + + // Check each class for cycles + for class := range allClasses { + if !visited[class] { + dfs(class, []string{}) + } + } + + return nil +} + +func main() { + if len(os.Args) < 2 { + fmt.Println("Usage: go run main.go ") + return + } + + directory := os.Args[1] + err := findCircularDependencies(directory) + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } +}