typespec_from_serializers 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/typespec_from_serializers/generator.rb +62 -44
- data/lib/typespec_from_serializers/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1bc90948b5d93848663bab0d1162a1f26d49d832a05ef4c57eb5cb1e90f74ff3
|
|
4
|
+
data.tar.gz: '008ddb8319166e72e2e75a30d840ad387a082df6e4d0846698e87f9b15ac1c05'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 950c7c34c0d3766854fd6eb4b3aa958b7ed8a20040ad8a43c5573d52741b156441b43e0fbded753536624d368ce353959f5f9e13d311eddea05ba75b8a4e85df
|
|
7
|
+
data.tar.gz: 6695700e9a0f73b03e97107d1844e2ef878dcf50217b45826418488827643923260f9b2465bd20fc4d03ef298ea2028f87132fa496abbb67f43ad635fda47562
|
data/CHANGELOG.md
CHANGED
|
@@ -980,56 +980,19 @@ module TypeSpecFromSerializers
|
|
|
980
980
|
|
|
981
981
|
# Internal: Extracts serializer class from controller method source using Prism AST
|
|
982
982
|
def extract_serializer_from_controller_method(controller_class, action)
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
method = controller_class.instance_method(action)
|
|
986
|
-
source_location = method.source_location
|
|
987
|
-
return nil unless source_location
|
|
988
|
-
|
|
989
|
-
file_path, line_number = source_location
|
|
990
|
-
return nil unless File.exist?(file_path)
|
|
991
|
-
|
|
992
|
-
# Parse the file with Prism
|
|
993
|
-
result = Prism.parse_file(file_path)
|
|
994
|
-
return nil unless result.success?
|
|
995
|
-
|
|
996
|
-
# Find the specific method definition node
|
|
997
|
-
method_finder = MethodFinder.new(action.to_s, line_number)
|
|
998
|
-
method_finder.visit(result.value)
|
|
999
|
-
return nil unless method_finder.method_node
|
|
983
|
+
method_node = find_action_node(controller_class, action)
|
|
984
|
+
return unless method_node
|
|
1000
985
|
|
|
1001
986
|
# Find serializer references only within this method
|
|
1002
987
|
visitor = SerializerVisitor.new
|
|
1003
|
-
visitor.visit(
|
|
988
|
+
visitor.visit(method_node)
|
|
1004
989
|
|
|
1005
990
|
# Try to constantize any found serializers and return the first valid one
|
|
1006
991
|
visitor.serializer_names.filter_map(&:safe_constantize).first
|
|
1007
992
|
rescue
|
|
1008
|
-
# File read or parsing error - return nil
|
|
1009
993
|
nil
|
|
1010
994
|
end
|
|
1011
995
|
|
|
1012
|
-
# Internal: Prism visitor to find a specific method definition by name and line
|
|
1013
|
-
class MethodFinder < Prism::Visitor
|
|
1014
|
-
attr_reader :method_node
|
|
1015
|
-
|
|
1016
|
-
def initialize(method_name, line_number)
|
|
1017
|
-
super()
|
|
1018
|
-
@method_name = method_name
|
|
1019
|
-
@line_number = line_number
|
|
1020
|
-
@method_node = nil
|
|
1021
|
-
end
|
|
1022
|
-
|
|
1023
|
-
def visit_def_node(node)
|
|
1024
|
-
# Match by method name and line number proximity
|
|
1025
|
-
if node.name.to_s == @method_name &&
|
|
1026
|
-
node.location.start_line <= @line_number &&
|
|
1027
|
-
node.location.end_line >= @line_number
|
|
1028
|
-
@method_node = node
|
|
1029
|
-
end
|
|
1030
|
-
super
|
|
1031
|
-
end
|
|
1032
|
-
end
|
|
1033
996
|
|
|
1034
997
|
# Internal: Prism visitor to extract serializer class names from AST
|
|
1035
998
|
class SerializerVisitor < Prism::Visitor
|
|
@@ -1124,10 +1087,8 @@ module TypeSpecFromSerializers
|
|
|
1124
1087
|
def extract_param_types_from_controller(controller_class, action)
|
|
1125
1088
|
param_types = {}
|
|
1126
1089
|
|
|
1127
|
-
#
|
|
1128
|
-
|
|
1129
|
-
param_methods = (controller_class.instance_methods(false) | controller_class.private_instance_methods(false))
|
|
1130
|
-
.select { |m| m.to_s.end_with?(config.param_method_suffix) }
|
|
1090
|
+
# Find which *_params methods are called by this action
|
|
1091
|
+
param_methods = find_params_methods_called_by_action(controller_class, action)
|
|
1131
1092
|
|
|
1132
1093
|
param_methods.each do |method_name|
|
|
1133
1094
|
type_found = false
|
|
@@ -1172,6 +1133,63 @@ module TypeSpecFromSerializers
|
|
|
1172
1133
|
{}
|
|
1173
1134
|
end
|
|
1174
1135
|
|
|
1136
|
+
# Internal: Finds *_params methods that are called by a specific action method
|
|
1137
|
+
def find_params_methods_called_by_action(controller_class, action)
|
|
1138
|
+
method_node = find_action_node(controller_class, action)
|
|
1139
|
+
return [] unless method_node
|
|
1140
|
+
|
|
1141
|
+
suffix = config.param_method_suffix
|
|
1142
|
+
find_method_calls(method_node)
|
|
1143
|
+
.select { |name| name.end_with?(suffix) }
|
|
1144
|
+
.map(&:to_sym)
|
|
1145
|
+
rescue
|
|
1146
|
+
[]
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
# Internal: Finds the AST node for a controller action method.
|
|
1150
|
+
def find_action_node(controller_class, action)
|
|
1151
|
+
return unless controller_class.method_defined?(action)
|
|
1152
|
+
|
|
1153
|
+
method = controller_class.instance_method(action)
|
|
1154
|
+
file_path, line_number = method.source_location
|
|
1155
|
+
return unless file_path && File.exist?(file_path)
|
|
1156
|
+
|
|
1157
|
+
find_method_at_line(file_path, line_number)
|
|
1158
|
+
end
|
|
1159
|
+
|
|
1160
|
+
# Internal: Parses a Ruby file and caches the result.
|
|
1161
|
+
def parse_file_cached(file_path)
|
|
1162
|
+
@parsed_files ||= {}
|
|
1163
|
+
@parsed_files[file_path] ||= begin
|
|
1164
|
+
result = Prism.parse_file(file_path)
|
|
1165
|
+
result.success? ? result.value : nil
|
|
1166
|
+
end
|
|
1167
|
+
end
|
|
1168
|
+
|
|
1169
|
+
# Internal: Finds a DefNode at the exact line number.
|
|
1170
|
+
def find_method_at_line(file_path, line_number)
|
|
1171
|
+
ast = parse_file_cached(file_path)
|
|
1172
|
+
return unless ast
|
|
1173
|
+
|
|
1174
|
+
queue = [ast]
|
|
1175
|
+
while (node = queue.shift)
|
|
1176
|
+
return node if node.is_a?(Prism::DefNode) && node.location.start_line == line_number
|
|
1177
|
+
queue.concat(node.compact_child_nodes)
|
|
1178
|
+
end
|
|
1179
|
+
nil
|
|
1180
|
+
end
|
|
1181
|
+
|
|
1182
|
+
# Internal: Finds all unqualified method call names in an AST node.
|
|
1183
|
+
def find_method_calls(node)
|
|
1184
|
+
calls = []
|
|
1185
|
+
queue = [node]
|
|
1186
|
+
while (current = queue.shift)
|
|
1187
|
+
calls << current.name.to_s if current.is_a?(Prism::CallNode) && current.receiver.nil?
|
|
1188
|
+
queue.concat(current.compact_child_nodes)
|
|
1189
|
+
end
|
|
1190
|
+
calls.uniq
|
|
1191
|
+
end
|
|
1192
|
+
|
|
1175
1193
|
# Internal: Extracts key-value types from Sorbet hash type
|
|
1176
1194
|
def extract_hash_types_from_sorbet(sorbet_type)
|
|
1177
1195
|
param_types = {}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typespec_from_serializers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Danila Poyarkov
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-12-
|
|
12
|
+
date: 2025-12-23 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: railties
|