Class: JsDuck::Class

Inherits:
Object
  • Object
show all
Defined in:
lib/jsduck/class.rb

Overview

Encapsulates class documentation and provides some commonly needed methods on it. Otherwise it acts like Hash, providing the [] method.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(doc, class_exists = true) ⇒ Class

Creates JSDuck class.

Pass true as second parameter to create a placeholder class.



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/jsduck/class.rb', line 19

def initialize(doc, class_exists=true)
  @doc = doc

  # Wrap classname into custom string class that allows
  # differenciating between existing and missing classes.
  @doc[:name] = ClassNameString.new(@doc[:name], class_exists)

  @doc[:members] = [] if !@doc[:members]

  @members_index = MembersIndex.new(self)

  @relations = nil
end

Instance Attribute Details

#members_indexObject

Used only by MembersIndex class itself to access the MembersIndex instances of parents and mixins.



14
15
16
# File 'lib/jsduck/class.rb', line 14

def members_index
  @members_index
end

#relationsObject

Returns the value of attribute relations.



10
11
12
# File 'lib/jsduck/class.rb', line 10

def relations
  @relations
end

Class Method Details

.constructor?(member) ⇒ Boolean

True if the given member is a constructor method

Returns:

  • (Boolean)


196
197
198
# File 'lib/jsduck/class.rb', line 196

def self.constructor?(member)
  member[:tagname] == :method && member[:name] == "constructor"
end

.member_id(m) ⇒ Object

Generates member :id from member hash



189
190
191
192
193
# File 'lib/jsduck/class.rb', line 189

def self.member_id(m)
  # Sanitize $ in member names with something safer
  name = m[:name].gsub(/\$/, 'S-')
  "#{m[:static] ? 'static-' : ''}#{m[:tagname]}-#{name}"
end

Instance Method Details

#[](key) ⇒ Object

Accessor to internal hash



60
61
62
# File 'lib/jsduck/class.rb', line 60

def [](key)
  @doc[key]
end

#[]=(key, value) ⇒ Object

Assignment to internal hash keys



65
66
67
# File 'lib/jsduck/class.rb', line 65

def []=(key, value)
  @doc[key] = value
end

#all_local_membersObject

Returns all local members of class



182
183
184
# File 'lib/jsduck/class.rb', line 182

def all_local_members
  @doc[:members]
end

#deps(type) ⇒ Object

Returns an array of class instances this class directly depends on. Possible types are:

  • :mixins

  • :requires

  • :uses



96
97
98
# File 'lib/jsduck/class.rb', line 96

def deps(type)
  @doc[type] ? @doc[type].collect {|classname| lookup(classname) } : []
end

#find_members(query = {}) ⇒ Object

Returns list of members filtered by a query. Searches both local and inherited members.

The query hash can contain the following fields:

  • :name : String - the name of the member to find.

  • :tagname : Symbol - the member type to look for.

  • :static : Boolean - true to only return static members,

    false to only return instance members.
    When nil or unspecified, both static
    and instance members are returned.
    
  • :local : Boolean - true to only return non-inherited members.

When called without arguments all members are returned.

When nothing found, an empty array is returned.



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/jsduck/class.rb', line 149

def find_members(query={})
  if query[:name]
    ms = @members_index.global_by_name[query[:name]] || []
    ms = ms.find_all {|m| m[:owner] == @doc[:name]} if query[:local]
  elsif query[:local]
    ms = @members_index.all_local
  else
    ms = @members_index.all_global
  end

  if query[:tagname]
    ms = ms.find_all {|m| m[:tagname] == query[:tagname] }
  end

  if query[:static] == true
    ms = ms.find_all {|m| m[:static] }
  elsif query[:static] == false
    ms = ms.reject {|m| m[:static] }
  end

  ms
end

#inherits_from?(class_name) ⇒ Boolean

Returns true when this class inherits from the specified class. Also returns true when the class itself is the one we are asking about.

Returns:

  • (Boolean)


126
127
128
# File 'lib/jsduck/class.rb', line 126

def inherits_from?(class_name)
  return @doc[:name] == class_name || (parent ? parent.inherits_from?(class_name) : false)
end

#internal_docObject

Returns the internal doc object.



34
35
36
# File 'lib/jsduck/class.rb', line 34

def internal_doc
  @doc
end

#internal_doc=(doc) ⇒ Object

Sets the internal doc object.

The doc object is processed in parallel and then assigned back through this method. But because of parallel processing the assigned doc object will not be just a modified old @doc but a completely new. If we were to just assign to @doc the #find_members caches would still point to old @doc members resulting in mysterious errors further along…



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/jsduck/class.rb', line 46

def internal_doc=(doc)
  @doc.merge!(doc) do |key, oldval, newval|
    if key == :members
      oldval.zip(newval) do |ms|
        ms[0].merge!(ms[1])
      end
      oldval
    else
      newval
    end
  end
end

#lookup(classname) ⇒ Object

Looks up class object by name When not found, prints warning message.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/jsduck/class.rb', line 107

def lookup(classname)
  if @relations[classname]
    @relations[classname]
  elsif @relations.ignore?(classname) || classname =~ /\*/
    # Ignore explicitly ignored classes and classnames with
    # wildcards in them.  We could expand the wildcard, but that
    # can result in a very long list of classes, like when
    # somebody requires 'Ext.form.*', so for now we do the
    # simplest thing and ignore it.
    Class.new({:name => classname}, false)
  else
    Logger.warn(:extend, "Class #{classname} not found", @doc[:files][0])
    # Create placeholder class
    Class.new({:name => classname}, false)
  end
end

#mixinsObject

Returns all direct mixins of this class. Same as #deps(:mixins).



85
86
87
# File 'lib/jsduck/class.rb', line 85

def mixins
  deps(:mixins)
end

#parentObject

Returns instance of parent class, or nil if there is none



70
71
72
# File 'lib/jsduck/class.rb', line 70

def parent
  @doc[:extends] ? lookup(@doc[:extends]) : nil
end

#parent_deps(type) ⇒ Object

Same ase #deps, but pulls out the dependencies from all parent classes.



101
102
103
# File 'lib/jsduck/class.rb', line 101

def parent_deps(type)
  parent ? parent.deps(type) + parent.parent_deps(type) : []
end

#refresh_member_ids!Object

This must be called whenever member hashes are changed. It updates the :id fields of members and clears the caches.



174
175
176
177
178
179
# File 'lib/jsduck/class.rb', line 174

def refresh_member_ids!
  @doc[:members].each do |m|
    m[:id] = Class.member_id(m)
  end
  @members_index.invalidate!
end

#superclassesObject

Returns array of ancestor classes. Example result when asking ancestors of MyPanel might be:

[Ext.util.Observable, Ext.Component, Ext.Panel]


79
80
81
82
# File 'lib/jsduck/class.rb', line 79

def superclasses
  p = parent
  p ? p.superclasses + [p]  : []
end