Class: DAP::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/dap/base.rb

Overview

Base class for DAP types

Direct Known Subclasses

AttachRequestArguments, Breakpoint, BreakpointEventBody, BreakpointLocation, BreakpointLocationsArguments, BreakpointLocationsResponseBody, CancelArguments, Capabilities, CapabilitiesEventBody, Checksum, ColumnDescriptor, CompletionItem, CompletionsArguments, CompletionsResponseBody, ContinueArguments, ContinueResponseBody, ContinuedEventBody, DataBreakpoint, DataBreakpointInfoArguments, DataBreakpointInfoResponseBody, DisassembleArguments, DisassembleResponseBody, DisassembledInstruction, DisconnectArguments, ErrorResponseBody, EvaluateArguments, EvaluateResponseBody, ExceptionBreakpointsFilter, ExceptionDetails, ExceptionInfoArguments, ExceptionInfoResponseBody, ExceptionOptions, ExceptionPathSegment, ExitedEventBody, FunctionBreakpoint, GotoArguments, GotoTarget, GotoTargetsArguments, GotoTargetsResponseBody, InitializeRequestArguments, InstructionBreakpoint, InvalidatedEventBody, LaunchRequestArguments, LoadedSourceEventBody, LoadedSourcesResponseBody, Message, Module, ModuleEventBody, ModulesArguments, ModulesResponseBody, NextArguments, OutputEventBody, PauseArguments, ProcessEventBody, ProgressEndEventBody, ProgressStartEventBody, ProgressUpdateEventBody, ProtocolMessage, ReadMemoryArguments, ReadMemoryResponseBody, RestartFrameArguments, ReverseContinueArguments, RunInTerminalRequestArguments, RunInTerminalResponseBody, Scope, ScopesArguments, ScopesResponseBody, SetBreakpointsArguments, SetBreakpointsResponseBody, SetDataBreakpointsArguments, SetDataBreakpointsResponseBody, SetExceptionBreakpointsArguments, SetExpressionArguments, SetExpressionResponseBody, SetFunctionBreakpointsArguments, SetFunctionBreakpointsResponseBody, SetInstructionBreakpointsArguments, SetInstructionBreakpointsResponseBody, SetVariableArguments, SetVariableResponseBody, Source, SourceArguments, SourceBreakpoint, SourceResponseBody, StackFrame, StackTraceArguments, StackTraceResponseBody, StepBackArguments, StepInArguments, StepInTarget, StepInTargetsArguments, StepInTargetsResponseBody, StepOutArguments, StoppedEventBody, TerminateArguments, TerminateThreadsArguments, TerminatedEventBody, Thread, ThreadEventBody, ThreadsResponseBody, ValueFormat, Variable, VariablePresentationHint, VariablesArguments, VariablesResponseBody

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(values) ⇒ Base

Create a new instance of the receiver.

Parameters:

  • values (Hash)

    the object’s attributes



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/dap/base.rb', line 120

def initialize(values)
  values.transform_keys!(&:to_sym)

  self.class.property_names.each do |k|
    v = values[k]

    transform = self.class.transform(k)
    v = transform.call(v, values) if transform

    self[k] = v
  end
end

Class Method Details

.build(values) {|values| ... } ⇒ Object

Build an instance of a DAP type.

Parameters:

  • values (Hash|String)

    attribute values or enum string

Yield Parameters:

  • values (Hash)

    normalized attribute values (optional)

Yield Returns:

  • (Class)

    the class to instantiate



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/dap/base.rb', line 7

def self.build(values, &block)
  values.transform_keys! &:to_sym if values.is_a? Hash

  if block.arity == 0
    klazz = yield
  else
    klazz = yield(values)
  end

  return values if values.is_a? klazz

  return klazz.from(values) if klazz < DAP::Enum

  klazz.new(values)
end

.emptyObject

Returns a relation that indicates a property is expected to be an empty object.



41
42
43
# File 'lib/dap/base.rb', line 41

def self.empty
  Class.new(DAP::Base)
end

.many(klazz) ⇒ Relation::Many

Returns a relation that indicates a property should be an array of the specified type.

Parameters:

  • klazz (Class)

    the expected type of members of the property

Returns:



27
28
29
# File 'lib/dap/base.rb', line 27

def self.many(klazz)
  DAP::Relation::Many.new(klazz)
end

.one_of(choices) ⇒ Relation::OneOf

Returns a relation that indicates a property should be one of a set of types.

Parameters:

  • choices (Hash[String, Class])

    the allowed property types

Returns:



35
36
37
# File 'lib/dap/base.rb', line 35

def self.one_of(choices)
  DAP::Relation::OneOf.new(choices)
end

.propertiesObject

Properties of the receiver.



97
98
99
100
101
102
# File 'lib/dap/base.rb', line 97

def self.properties
  @properties ||= []
  return @properties if self == DAP::Base

  superclass.properties + @properties
end

.property(*names, as: nil, required: true) ⇒ Object

Defines a property or properties.

Parameters:

  • names (Array<Symbol>)

    the properties

  • as (Class|Relation|String) (defaults to: nil)

    the expected type of the property

  • required (Boolean) (defaults to: true)

    whether the property is required



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/dap/base.rb', line 49

def self.property(*names, as: nil, required: true)
  @properties ||= []
  @transformations ||= {}

  klazz = name

  names.each do |name|
    case as
    when nil, String
      # ignore

    when Class
      DAP::Relation.supported!(as)

      transform = ->(value, values, invert: false) { value.nil? ? nil : invert ? value.to_wire : build(value || {}) { as } }

    when DAP::Relation::Many
      transform = ->(value, values, invert: false) { value.nil? ? nil : invert ? value.map(&:to_wire) : value.map { |v| build(v) { as.klazz } } }

    when DAP::Relation::OneOf
      transform = ->(value, values, invert: false) do
        return value.to_wire if invert

        build(value || {}) do
          key = values[as.key]&.to_sym
          raise "#{klazz}.#{as.key} missing" if key.nil?
          raise "Unknown #{klazz}.#{as.key}: '#{key}'" unless as.types.key?(key)

          as.types[key]
        end
      end

    else
      raise "Invalid property constraint: #{as.class} #{as.inspect}"
    end

    @properties << {
      name: name,
      transform: transform,
      required: required
    }
  end


  attr_reader(*names)
end

.property_namesObject

Names of the receiver’s properties.



105
106
107
# File 'lib/dap/base.rb', line 105

def self.property_names
  properties.map { |p| p[:name] }
end

.transform(name) ⇒ Proc

Retreives the transform for the named property.

Parameters:

  • name (String)

    the property name

Returns:

  • (Proc)

    the transform



112
113
114
115
116
# File 'lib/dap/base.rb', line 112

def self.transform(name)
  (@properties || []).each { |p| return p[:transform] if p[:name] == name && p[:transform] }

  return superclass.transform(name) unless self == DAP::Base
end

Instance Method Details

#[](key) ⇒ Object



170
171
172
173
# File 'lib/dap/base.rb', line 170

def [](key)
  key = key.to_sym
  instance_variable_get("@#{key}".to_sym) if self.class.property_names.include? key
end

#to_wireHash

Convert the receiver to a form suitable for encoding.

Returns:

  • (Hash)


155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/dap/base.rb', line 155

def to_wire
  self.class.property_names.each_with_object({}) do |k, h|
    v = self[k]
    next if v.nil?

    if transform = self.class.transform(k)
      v = transform.call(v, self, invert: true) if transform
    else
      v = convert_complex(v)
    end

    h[k] = v
  end
end

#validate!Object

Validate property values against their expectations.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/dap/base.rb', line 134

def validate!
  self.class.properties.each do |p|
    key, required = p[:name], p[:required]
    value = self[key]
    if value.nil?
      raise "Property #{key} of #{self.class} is required" if required
      next
    end

    if value.respond_to?(:validate!)
      value.validate!
    elsif value.respond_to?(:each)
      value.each { |v| v.validate! if v.respond_to?(:validate!) }
    end
  end

  self
end