light-services 3.0.0 → 3.1.1
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/.rubocop.yml +7 -1
- data/CHANGELOG.md +21 -0
- data/CLAUDE.md +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +11 -11
- data/docs/{readme.md → README.md} +12 -11
- data/docs/{summary.md → SUMMARY.md} +11 -1
- data/docs/arguments.md +23 -0
- data/docs/concepts.md +19 -19
- data/docs/configuration.md +36 -0
- data/docs/errors.md +31 -1
- data/docs/outputs.md +23 -0
- data/docs/quickstart.md +1 -1
- data/docs/rubocop.md +285 -0
- data/docs/ruby-lsp.md +133 -0
- data/docs/steps.md +62 -8
- data/docs/testing.md +1 -1
- data/lib/light/services/base.rb +110 -7
- data/lib/light/services/base_with_context.rb +23 -1
- data/lib/light/services/callbacks.rb +293 -41
- data/lib/light/services/collection.rb +50 -2
- data/lib/light/services/concerns/execution.rb +3 -0
- data/lib/light/services/config.rb +83 -3
- data/lib/light/services/constants.rb +3 -0
- data/lib/light/services/dsl/arguments_dsl.rb +1 -0
- data/lib/light/services/dsl/outputs_dsl.rb +1 -0
- data/lib/light/services/dsl/validation.rb +30 -0
- data/lib/light/services/exceptions.rb +19 -1
- data/lib/light/services/message.rb +28 -3
- data/lib/light/services/messages.rb +74 -2
- data/lib/light/services/rubocop/cop/light_services/argument_type_required.rb +52 -0
- data/lib/light/services/rubocop/cop/light_services/condition_method_exists.rb +173 -0
- data/lib/light/services/rubocop/cop/light_services/deprecated_methods.rb +113 -0
- data/lib/light/services/rubocop/cop/light_services/dsl_order.rb +176 -0
- data/lib/light/services/rubocop/cop/light_services/missing_private_keyword.rb +102 -0
- data/lib/light/services/rubocop/cop/light_services/no_direct_instantiation.rb +66 -0
- data/lib/light/services/rubocop/cop/light_services/output_type_required.rb +52 -0
- data/lib/light/services/rubocop/cop/light_services/step_method_exists.rb +109 -0
- data/lib/light/services/rubocop.rb +12 -0
- data/lib/light/services/settings/field.rb +33 -5
- data/lib/light/services/settings/step.rb +23 -5
- data/lib/light/services/version.rb +1 -1
- data/lib/ruby_lsp/light_services/addon.rb +36 -0
- data/lib/ruby_lsp/light_services/definition.rb +132 -0
- data/lib/ruby_lsp/light_services/indexing_enhancement.rb +263 -0
- metadata +17 -3
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyLsp
|
|
4
|
+
module LightServices
|
|
5
|
+
class Definition
|
|
6
|
+
# Condition options that reference methods
|
|
7
|
+
CONDITION_OPTIONS = [:if, :unless].freeze
|
|
8
|
+
|
|
9
|
+
def initialize(response_builder, uri, node_context, index, dispatcher)
|
|
10
|
+
@response_builder = response_builder
|
|
11
|
+
@uri = uri
|
|
12
|
+
@node_context = node_context
|
|
13
|
+
@index = index
|
|
14
|
+
|
|
15
|
+
# Register for symbol nodes - this is what gets triggered when user clicks on :method_name
|
|
16
|
+
dispatcher.register(self, :on_symbol_node_enter)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Called when cursor is on a symbol node (e.g., :validate in `step :validate`)
|
|
20
|
+
def on_symbol_node_enter(node)
|
|
21
|
+
# Check if this symbol is part of a step call by examining the call context
|
|
22
|
+
call_node = find_parent_step_call
|
|
23
|
+
return unless call_node
|
|
24
|
+
|
|
25
|
+
method_name = determine_method_name(node, call_node)
|
|
26
|
+
return unless method_name
|
|
27
|
+
|
|
28
|
+
find_and_append_method_location(method_name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# Find the parent step call node from the node context
|
|
34
|
+
# The node_context.call_node returns the enclosing call if cursor is on an argument
|
|
35
|
+
def find_parent_step_call
|
|
36
|
+
call_node = @node_context.call_node
|
|
37
|
+
return unless call_node
|
|
38
|
+
return unless call_node.name == :step
|
|
39
|
+
|
|
40
|
+
call_node
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Determine which method name to look up based on where the symbol appears
|
|
44
|
+
# Returns nil if this symbol is not a method reference we should handle
|
|
45
|
+
def determine_method_name(symbol_node, call_node)
|
|
46
|
+
symbol_value = symbol_node.value.to_sym
|
|
47
|
+
|
|
48
|
+
# Check if this is the first argument (step method name)
|
|
49
|
+
first_arg = call_node.arguments&.arguments&.first
|
|
50
|
+
if first_arg.is_a?(Prism::SymbolNode) && first_arg.value.to_sym == symbol_value && same_location?(first_arg,
|
|
51
|
+
symbol_node)
|
|
52
|
+
# Verify the symbol node location matches (same node, not just same value)
|
|
53
|
+
return symbol_value.to_s
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Check if this is a condition option (if: or unless:)
|
|
57
|
+
keyword_hash = find_keyword_hash(call_node)
|
|
58
|
+
return unless keyword_hash
|
|
59
|
+
|
|
60
|
+
CONDITION_OPTIONS.each do |option_name|
|
|
61
|
+
condition_symbol = find_symbol_option(keyword_hash, option_name)
|
|
62
|
+
next unless condition_symbol
|
|
63
|
+
next unless same_location?(condition_symbol, symbol_node)
|
|
64
|
+
|
|
65
|
+
return condition_symbol.value.to_s
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Check if two nodes have the same location (are the same node)
|
|
72
|
+
def same_location?(node1, node2)
|
|
73
|
+
node1.location.start_offset == node2.location.start_offset &&
|
|
74
|
+
node1.location.end_offset == node2.location.end_offset
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Find the keyword hash in call arguments
|
|
78
|
+
def find_keyword_hash(node)
|
|
79
|
+
node.arguments&.arguments&.find { |arg| arg.is_a?(Prism::KeywordHashNode) }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Find a symbol value for a specific option in the keyword hash
|
|
83
|
+
# Returns the SymbolNode if found and value is a symbol, nil otherwise
|
|
84
|
+
def find_symbol_option(keyword_hash, option_name)
|
|
85
|
+
element = keyword_hash.elements.find do |elem|
|
|
86
|
+
elem.is_a?(Prism::AssocNode) &&
|
|
87
|
+
elem.key.is_a?(Prism::SymbolNode) &&
|
|
88
|
+
elem.key.value.to_sym == option_name
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
return unless element
|
|
92
|
+
return unless element.value.is_a?(Prism::SymbolNode)
|
|
93
|
+
|
|
94
|
+
element.value
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Find method definition in index and append location to response
|
|
98
|
+
def find_and_append_method_location(method_name)
|
|
99
|
+
owner_name = @node_context.nesting.join("::")
|
|
100
|
+
return if owner_name.empty?
|
|
101
|
+
|
|
102
|
+
# Look up method entries in the index
|
|
103
|
+
method_entries = @index.resolve_method(method_name, owner_name)
|
|
104
|
+
return unless method_entries&.any?
|
|
105
|
+
|
|
106
|
+
method_entries.each { |entry| append_location(entry) }
|
|
107
|
+
|
|
108
|
+
true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def append_location(entry)
|
|
112
|
+
@response_builder << Interface::Location.new(
|
|
113
|
+
uri: URI::Generic.from_path(path: entry.file_path).to_s,
|
|
114
|
+
range: build_range(entry.location),
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def build_range(location)
|
|
119
|
+
Interface::Range.new(
|
|
120
|
+
start: Interface::Position.new(
|
|
121
|
+
line: location.start_line - 1,
|
|
122
|
+
character: location.start_column,
|
|
123
|
+
),
|
|
124
|
+
end: Interface::Position.new(
|
|
125
|
+
line: location.end_line - 1,
|
|
126
|
+
character: location.end_column,
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyLsp
|
|
4
|
+
module LightServices
|
|
5
|
+
class IndexingEnhancement < RubyIndexer::Enhancement # rubocop:disable Metrics/ClassLength
|
|
6
|
+
# DSL methods that generate getter, predicate, and setter methods
|
|
7
|
+
FIELD_DSL_METHODS = [:arg, :output].freeze
|
|
8
|
+
|
|
9
|
+
# Default type mappings for common dry-types to their underlying Ruby types
|
|
10
|
+
# These can be extended via Light::Services.config.ruby_lsp_type_mappings
|
|
11
|
+
DEFAULT_TYPE_MAPPINGS = {
|
|
12
|
+
"Types::String" => "String",
|
|
13
|
+
"Types::Strict::String" => "String",
|
|
14
|
+
"Types::Coercible::String" => "String",
|
|
15
|
+
"Types::Integer" => "Integer",
|
|
16
|
+
"Types::Strict::Integer" => "Integer",
|
|
17
|
+
"Types::Coercible::Integer" => "Integer",
|
|
18
|
+
"Types::Float" => "Float",
|
|
19
|
+
"Types::Strict::Float" => "Float",
|
|
20
|
+
"Types::Coercible::Float" => "Float",
|
|
21
|
+
"Types::Decimal" => "BigDecimal",
|
|
22
|
+
"Types::Strict::Decimal" => "BigDecimal",
|
|
23
|
+
"Types::Coercible::Decimal" => "BigDecimal",
|
|
24
|
+
"Types::Bool" => "TrueClass | FalseClass",
|
|
25
|
+
"Types::Strict::Bool" => "TrueClass | FalseClass",
|
|
26
|
+
"Types::True" => "TrueClass",
|
|
27
|
+
"Types::Strict::True" => "TrueClass",
|
|
28
|
+
"Types::False" => "FalseClass",
|
|
29
|
+
"Types::Strict::False" => "FalseClass",
|
|
30
|
+
"Types::Array" => "Array",
|
|
31
|
+
"Types::Strict::Array" => "Array",
|
|
32
|
+
"Types::Hash" => "Hash",
|
|
33
|
+
"Types::Strict::Hash" => "Hash",
|
|
34
|
+
"Types::Symbol" => "Symbol",
|
|
35
|
+
"Types::Strict::Symbol" => "Symbol",
|
|
36
|
+
"Types::Coercible::Symbol" => "Symbol",
|
|
37
|
+
"Types::Date" => "Date",
|
|
38
|
+
"Types::Strict::Date" => "Date",
|
|
39
|
+
"Types::DateTime" => "DateTime",
|
|
40
|
+
"Types::Strict::DateTime" => "DateTime",
|
|
41
|
+
"Types::Time" => "Time",
|
|
42
|
+
"Types::Strict::Time" => "Time",
|
|
43
|
+
"Types::Nil" => "NilClass",
|
|
44
|
+
"Types::Strict::Nil" => "NilClass",
|
|
45
|
+
"Types::Any" => "Object",
|
|
46
|
+
}.freeze
|
|
47
|
+
|
|
48
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
49
|
+
# Public API - Called by Ruby LSP indexer
|
|
50
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
# Called when the indexer encounters a method call node
|
|
53
|
+
# Detects `arg` and `output` DSL calls and registers the generated methods
|
|
54
|
+
def on_call_node_enter(node)
|
|
55
|
+
return unless @listener.current_owner
|
|
56
|
+
return unless FIELD_DSL_METHODS.include?(node.name)
|
|
57
|
+
|
|
58
|
+
field_name = extract_field_name(node)
|
|
59
|
+
return unless field_name
|
|
60
|
+
|
|
61
|
+
ruby_type = extract_ruby_type(node)
|
|
62
|
+
register_field_methods(field_name, node.location, ruby_type)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def on_call_node_leave(node); end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
70
|
+
# Field Extraction
|
|
71
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
# Extract the field name from the first argument (symbol)
|
|
74
|
+
# Example: `arg :user` → "user"
|
|
75
|
+
def extract_field_name(node)
|
|
76
|
+
arguments = node.arguments&.arguments
|
|
77
|
+
return unless arguments&.any?
|
|
78
|
+
|
|
79
|
+
first_arg = arguments.first
|
|
80
|
+
return unless first_arg.is_a?(Prism::SymbolNode)
|
|
81
|
+
|
|
82
|
+
first_arg.value
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
86
|
+
# Type Resolution
|
|
87
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
# Extract and resolve the Ruby type from the `type:` keyword argument
|
|
90
|
+
# Returns the mapped Ruby type string or the original type if no mapping exists
|
|
91
|
+
def extract_ruby_type(node)
|
|
92
|
+
type_node = find_type_value_node(node)
|
|
93
|
+
return unless type_node
|
|
94
|
+
|
|
95
|
+
resolve_to_ruby_type(type_node)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Find the value node for the `type:` keyword argument
|
|
99
|
+
def find_type_value_node(node)
|
|
100
|
+
arguments = node.arguments&.arguments
|
|
101
|
+
return unless arguments
|
|
102
|
+
|
|
103
|
+
keyword_hash = arguments.find { |arg| arg.is_a?(Prism::KeywordHashNode) }
|
|
104
|
+
return unless keyword_hash
|
|
105
|
+
|
|
106
|
+
# NOTE: Prism's SymbolNode#value returns a String, not a Symbol
|
|
107
|
+
type_element = keyword_hash.elements.find do |element|
|
|
108
|
+
element.is_a?(Prism::AssocNode) &&
|
|
109
|
+
element.key.is_a?(Prism::SymbolNode) &&
|
|
110
|
+
element.key.value == "type"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
type_element&.value
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Resolve a Prism type node to a Ruby type string
|
|
117
|
+
# Handles constants, constant paths, and method chains
|
|
118
|
+
def resolve_to_ruby_type(node)
|
|
119
|
+
type_string = node_to_constant_string(node)
|
|
120
|
+
return unless type_string
|
|
121
|
+
|
|
122
|
+
map_to_ruby_type(type_string) || type_string
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Convert a Prism node to its constant string representation
|
|
126
|
+
def node_to_constant_string(node)
|
|
127
|
+
case node
|
|
128
|
+
when Prism::ConstantReadNode
|
|
129
|
+
node.name.to_s
|
|
130
|
+
when Prism::ConstantPathNode
|
|
131
|
+
build_constant_path(node)
|
|
132
|
+
when Prism::CallNode
|
|
133
|
+
# Handle method chains like Types::String.constrained(...) or Types::Array.of(...)
|
|
134
|
+
extract_receiver_constant(node)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Build a full constant path string from nested ConstantPathNodes
|
|
139
|
+
# Example: Types::Strict::String
|
|
140
|
+
def build_constant_path(node)
|
|
141
|
+
parts = []
|
|
142
|
+
current = node
|
|
143
|
+
|
|
144
|
+
while current.is_a?(Prism::ConstantPathNode)
|
|
145
|
+
parts.unshift(current.name.to_s)
|
|
146
|
+
current = current.parent
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
parts.unshift(current.name.to_s) if current.is_a?(Prism::ConstantReadNode)
|
|
150
|
+
parts.join("::")
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Extract the receiver constant from a method call chain
|
|
154
|
+
# Example: Types::String.constrained(format: /@/) → "Types::String"
|
|
155
|
+
def extract_receiver_constant(node)
|
|
156
|
+
receiver = node.receiver
|
|
157
|
+
return unless receiver
|
|
158
|
+
|
|
159
|
+
case receiver
|
|
160
|
+
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
|
161
|
+
node_to_constant_string(receiver)
|
|
162
|
+
when Prism::CallNode
|
|
163
|
+
extract_receiver_constant(receiver)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
168
|
+
# Type Mapping
|
|
169
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
# Map a type string to its corresponding Ruby type
|
|
172
|
+
# Uses custom mappings from config (if available) merged with defaults
|
|
173
|
+
def map_to_ruby_type(type_string)
|
|
174
|
+
mappings = effective_type_mappings
|
|
175
|
+
|
|
176
|
+
# Direct mapping lookup (custom mappings take precedence)
|
|
177
|
+
return mappings[type_string] if mappings.key?(type_string)
|
|
178
|
+
|
|
179
|
+
# Handle parameterized types: Types::Array.of(...) → Types::Array
|
|
180
|
+
base_type = type_string.split(".").first
|
|
181
|
+
mappings[base_type]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Returns the effective type mappings (defaults + custom from config)
|
|
185
|
+
# Custom mappings take precedence over defaults
|
|
186
|
+
def effective_type_mappings
|
|
187
|
+
return DEFAULT_TYPE_MAPPINGS unless defined?(Light::Services)
|
|
188
|
+
return DEFAULT_TYPE_MAPPINGS unless Light::Services.respond_to?(:config)
|
|
189
|
+
|
|
190
|
+
custom_mappings = Light::Services.config&.ruby_lsp_type_mappings
|
|
191
|
+
return DEFAULT_TYPE_MAPPINGS if custom_mappings.nil? || custom_mappings.empty?
|
|
192
|
+
|
|
193
|
+
DEFAULT_TYPE_MAPPINGS.merge(custom_mappings)
|
|
194
|
+
rescue NoMethodError
|
|
195
|
+
DEFAULT_TYPE_MAPPINGS
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
199
|
+
# Method Registration
|
|
200
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
# Register all three generated methods for a field (getter, predicate, setter)
|
|
203
|
+
def register_field_methods(field_name, location, ruby_type)
|
|
204
|
+
register_getter(field_name, location, ruby_type)
|
|
205
|
+
register_predicate(field_name, location)
|
|
206
|
+
register_setter(field_name, location, ruby_type)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def register_getter(field_name, location, ruby_type)
|
|
210
|
+
@listener.add_method(
|
|
211
|
+
field_name.to_s,
|
|
212
|
+
location,
|
|
213
|
+
no_params_signature,
|
|
214
|
+
comments: return_type_comment(ruby_type),
|
|
215
|
+
)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def register_predicate(field_name, location)
|
|
219
|
+
@listener.add_method(
|
|
220
|
+
"#{field_name}?",
|
|
221
|
+
location,
|
|
222
|
+
no_params_signature,
|
|
223
|
+
comments: "@return [Boolean]",
|
|
224
|
+
)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def register_setter(field_name, location, ruby_type)
|
|
228
|
+
@listener.add_method(
|
|
229
|
+
"#{field_name}=",
|
|
230
|
+
location,
|
|
231
|
+
value_param_signature,
|
|
232
|
+
comments: setter_comment(ruby_type),
|
|
233
|
+
)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
237
|
+
# Signatures & Comments
|
|
238
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
239
|
+
|
|
240
|
+
def no_params_signature
|
|
241
|
+
[RubyIndexer::Entry::Signature.new([])]
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def value_param_signature
|
|
245
|
+
[RubyIndexer::Entry::Signature.new([
|
|
246
|
+
RubyIndexer::Entry::RequiredParameter.new(name: :value),
|
|
247
|
+
])]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def return_type_comment(ruby_type)
|
|
251
|
+
return nil unless ruby_type
|
|
252
|
+
|
|
253
|
+
"@return [#{ruby_type}]"
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def setter_comment(ruby_type)
|
|
257
|
+
return "@param value the value to set" unless ruby_type
|
|
258
|
+
|
|
259
|
+
"@param value [#{ruby_type}] the value to set\n@return [#{ruby_type}]"
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: light-services
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Kodkod
|
|
@@ -34,6 +34,8 @@ files:
|
|
|
34
34
|
- Rakefile
|
|
35
35
|
- bin/console
|
|
36
36
|
- bin/setup
|
|
37
|
+
- docs/README.md
|
|
38
|
+
- docs/SUMMARY.md
|
|
37
39
|
- docs/arguments.md
|
|
38
40
|
- docs/best-practices.md
|
|
39
41
|
- docs/callbacks.md
|
|
@@ -46,11 +48,11 @@ files:
|
|
|
46
48
|
- docs/outputs.md
|
|
47
49
|
- docs/pundit-authorization.md
|
|
48
50
|
- docs/quickstart.md
|
|
49
|
-
- docs/readme.md
|
|
50
51
|
- docs/recipes.md
|
|
52
|
+
- docs/rubocop.md
|
|
53
|
+
- docs/ruby-lsp.md
|
|
51
54
|
- docs/service-rendering.md
|
|
52
55
|
- docs/steps.md
|
|
53
|
-
- docs/summary.md
|
|
54
56
|
- docs/testing.md
|
|
55
57
|
- lib/generators/light_services/install/USAGE
|
|
56
58
|
- lib/generators/light_services/install/install_generator.rb
|
|
@@ -86,10 +88,22 @@ files:
|
|
|
86
88
|
- lib/light/services/rspec/matchers/have_error_on.rb
|
|
87
89
|
- lib/light/services/rspec/matchers/have_warning_on.rb
|
|
88
90
|
- lib/light/services/rspec/matchers/trigger_callback.rb
|
|
91
|
+
- lib/light/services/rubocop.rb
|
|
92
|
+
- lib/light/services/rubocop/cop/light_services/argument_type_required.rb
|
|
93
|
+
- lib/light/services/rubocop/cop/light_services/condition_method_exists.rb
|
|
94
|
+
- lib/light/services/rubocop/cop/light_services/deprecated_methods.rb
|
|
95
|
+
- lib/light/services/rubocop/cop/light_services/dsl_order.rb
|
|
96
|
+
- lib/light/services/rubocop/cop/light_services/missing_private_keyword.rb
|
|
97
|
+
- lib/light/services/rubocop/cop/light_services/no_direct_instantiation.rb
|
|
98
|
+
- lib/light/services/rubocop/cop/light_services/output_type_required.rb
|
|
99
|
+
- lib/light/services/rubocop/cop/light_services/step_method_exists.rb
|
|
89
100
|
- lib/light/services/settings/field.rb
|
|
90
101
|
- lib/light/services/settings/step.rb
|
|
91
102
|
- lib/light/services/utils.rb
|
|
92
103
|
- lib/light/services/version.rb
|
|
104
|
+
- lib/ruby_lsp/light_services/addon.rb
|
|
105
|
+
- lib/ruby_lsp/light_services/definition.rb
|
|
106
|
+
- lib/ruby_lsp/light_services/indexing_enhancement.rb
|
|
93
107
|
- light-services.gemspec
|
|
94
108
|
homepage: https://light-services-docs.vercel.app/
|
|
95
109
|
licenses:
|