Class: RBS::Namespace

Inherits:
Object
  • Object
show all
Defined in:
sig/namespace.rbs,
lib/rbs/namespace.rb

Overview

Namespace instance represents a prefix of module names.

vvvvvvvvvvvvvv  TypeName
RBS::Namespace
^^^^^           Namespace

vvvvvvvvvv    TypeName
RBS::Types
^^^^^         Namespace

vvvvvvvvvvvvvvvvv    TypeName
RBS::Types::Union
^^^^^^^^^^^^         Namespace

Note that Namespace is an RBS specific concept and there is no corresponding concept in Ruby.

There are absolute and relative namespaces.

Namespace(::RBS::)         # Absolute namespace
Namespace(  RBS::)         # Relative namespace

It also defines two special namespaces.

::              # _Root_ namespace
                # _Empty_ namespace

Constant Summary collapse

INTERN_LEAF =

Returns:

Module.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path:, absolute:) ⇒ Namespace

Returns a new instance of Namespace.

Parameters:

  • path: (Array[Symbol])
  • absolute: (boolish)


7
8
9
10
# File 'lib/rbs/namespace.rb', line 7

def initialize(path:, absolute:)
  @path = path
  @absolute = absolute ? true : false
end

Instance Attribute Details

#pathArray[Symbol] (readonly)

Returns the value of attribute path.

Returns:

  • (Array[Symbol])


5
6
7
# File 'lib/rbs/namespace.rb', line 5

def path
  @path
end

Class Method Details

.[](path, absolute) ⇒ Namespace

Returns an interned Namespace instance.

Subsequent calls with structurally equal path and absolute arguments return the same object. The internal path array is duplicated and frozen before being cached.

Parameters:

  • path (Array[Symbol])
  • absolute (boolish)

Returns:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rbs/namespace.rb', line 24

def self.[](path, absolute)
  absolute = absolute ? true : false

  # Lock-free fast path.
  node = absolute ? @intern_trie_absolute : @intern_trie_relative
  path.each do |sym|
    node = node[sym]
    break unless node
  end
  if node && (cached = node[INTERN_LEAF])
    return cached
  end

  @intern_mutex.synchronize do
    node = absolute ? @intern_trie_absolute : @intern_trie_relative
    path.each { |sym| node = (node[sym] ||= {}) }
    node[INTERN_LEAF] ||= begin
      frozen_path = path.frozen? ? path : path.dup.freeze
      new(path: frozen_path, absolute: absolute)
    end
  end
end

.emptyNamespace

Returns new empty namespace.

Returns:



68
69
70
# File 'sig/namespace.rbs', line 68

def self.empty
  @empty ||= self[[], false]
end

.parse(string) ⇒ Namespace

Parameters:

  • string (String)

Returns:



129
130
131
132
133
134
135
# File 'lib/rbs/namespace.rb', line 129

def self.parse(string)
  if string.start_with?("::")
    self[string.split("::").drop(1).map(&:to_sym), true]
  else
    self[string.split("::").map(&:to_sym), false]
  end
end

.rootNamespace

Returns new root namespace.

Returns:



71
72
73
# File 'sig/namespace.rbs', line 71

def self.root
  @root ||= self[[], true]
end

Instance Method Details

#+(other) ⇒ Namespace

Concat two namespaces.

Namespace("Foo::") + Namespace("Bar::")   # => Foo::Bar::
Namespace("::Foo::") + Namespace("Bar::") # => ::Foo::Bar::

If other is an absolute namespace, it returns other.

Namespace("Foo::") + Namespace("::Bar::")  # =>  ::Bar::

Parameters:

Returns:



85
86
87
88
89
90
91
# File 'sig/namespace.rbs', line 85

def +(other)
  if other.absolute?
    other
  else
    Namespace[path + other.path, absolute?]
  end
end

#==(other) ⇒ Boolean Also known as: eql?

Equality is defined by its structure.

Parameters:

  • other (Object)

Returns:

  • (Boolean)


126
127
128
129
# File 'sig/namespace.rbs', line 126

def ==(other)
  return true if equal?(other)
  other.is_a?(Namespace) && other.path == path && other.absolute? == absolute?
end

#absolute!Namespace

Returns absolute namespace.

Namespace("A").absolute!      # => Namespace("::A")
Namespace("::A").absolute!    # => Namespace("::A")

Returns:



116
117
118
# File 'sig/namespace.rbs', line 116

def absolute!
  Namespace[path, true]
end

#absolute?Boolean

Returns true if self is absolute namespace.

Returns:

  • (Boolean)


105
106
107
# File 'sig/namespace.rbs', line 105

def absolute?
  @absolute
end

#append(component) ⇒ Namespace

Add one path component to self.

Namespace("Foo::").append(:Bar) # => Namespace("Foo::Bar::")

Parameters:

  • component (Symbol)

Returns:



92
93
94
# File 'sig/namespace.rbs', line 92

def append(component)
  Namespace[path + [component], absolute?]
end

#ascendvoid #ascendEnumerator[Namespace, void]

Iterate over Namespace for each element in ascending order.

Namespace.parse("::A::B::C").ascend {|ns| p ns }
  # => ::A::B::C
  # => ::A::B
  # => ::A
  # => ::(root)

Overloads:

  • #ascendvoid

    This method returns an undefined value.

  • #ascendEnumerator[Namespace, void]

    Returns:

Yields:

Yield Parameters:

Yield Returns:

  • (void)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'sig/namespace.rbs', line 158

def ascend
  if block_given?
    current = self

    until current.empty?
      yield current
      current = _ = current.parent
    end

    yield current

    self
  else
    enum_for(:ascend)
  end
end

#empty?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/rbs/namespace.rb', line 90

def empty?
  path.empty?
end

#hashInteger

Hash is defined based on its structure.

Returns:

  • (Integer)


132
133
134
# File 'sig/namespace.rbs', line 132

def hash
  @hash ||= path.hash ^ absolute?.hash
end

#parentNamespace

Returns parent namespace. Raises error there is no parent namespace.

Namespace("::A").parent    # => Namespace("::")
Namespace("::").parent     # raises error
Namespace("A::B").parent   # => Namespace("A")

Returns:



102
103
104
105
106
107
# File 'sig/namespace.rbs', line 102

def parent
  @parent ||= begin
    raise "Parent with empty namespace" if empty?
    Namespace[path.take(path.size - 1), absolute?]
  end
end

#relative!Namespace

Returns relative namespace.

Returns:



120
121
122
# File 'sig/namespace.rbs', line 120

def relative!
  Namespace[path, false]
end

#relative?Boolean

Returns true if self is relative namespace.

Returns:

  • (Boolean)


108
109
110
# File 'sig/namespace.rbs', line 108

def relative?
  !absolute?
end

#split[Namespace, Symbol]?

Returns a pair of parent namespace and a symbol of last component.

Namespace("::A::B::C").split    # => [Namespace("::A::B::"), :C]

Returns:



139
140
141
142
143
# File 'sig/namespace.rbs', line 139

def split
  last = path.last or return
  parent = self.parent
  [parent, last]
end

#to_sString

Returns:

  • (String)


111
112
113
114
115
116
117
118
# File 'lib/rbs/namespace.rb', line 111

def to_s
  if empty?
    absolute? ? "::" : ""
  else
    s = path.join("::")
    absolute? ? "::#{s}::" : "#{s}::"
  end
end

#to_type_nameTypeName

Construct a type name which points to the same name type.

Returns:



145
146
147
148
149
150
151
152
# File 'sig/namespace.rbs', line 145

def to_type_name
  parent, name = split

  raise unless name
  raise unless parent

  TypeName[parent, name]
end