Class: JsDuck::Aggregator

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

Overview

Combines JavaScript Parser, DocParser and Merger. Produces array of classes as result.

Instance Method Summary collapse

Constructor Details

#initializeAggregator

Returns a new instance of Aggregator.



12
13
14
15
16
17
18
# File 'lib/jsduck/aggregator.rb', line 12

def initialize
  @documentation = []
  @classes = {}
  @alt_names = {}
  @orphans = []
  @current_class = nil
end

Instance Method Details

#add_class(cls) ⇒ Object

When class exists, merge it with class node. Otherwise add as new class.



43
44
45
46
47
48
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
# File 'lib/jsduck/aggregator.rb', line 43

def add_class(cls)
  old_cls = @classes[cls[:name]]
  if !old_cls && @alt_names[cls[:name]]
    old_cls = @alt_names[cls[:name]]
    warn_alt_name(cls)
  end

  if old_cls
    merge_classes(old_cls, cls)
    @current_class = old_cls
  else
    @current_class = cls
    @documentation << cls
    @classes[cls[:name]] = cls

    # Register all alternate names of class for lookup too
    cls[:alternateClassNames].each do |altname|
      if cls[:name] == altname
        # A buggy documentation, warn.
        warn_alt_name(cls)
      else
        @alt_names[altname] = cls
        # When an alternate name has been used as a class name before,
        # then this is one crappy documentation, but attempt to handle
        # it by merging the class with alt-name into this class.
        if @classes[altname]
          merge_classes(cls, @classes[altname])
          @documentation.delete(@classes[altname])
          @classes.delete(altname)
          warn_alt_name(cls)
        end
      end
    end

    insert_orphans(cls)
  end
end

#add_empty_class(name, doc = "") ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/jsduck/aggregator.rb', line 183

def add_empty_class(name, doc = "")
  add_class({
    :tagname => :class,
    :name => name,
    :doc => doc,
    :mixins => [],
    :alternateClassNames => [],
    :members => [],
    :aliases => {},
    :meta => {},
    :files => [{:filename => "", :linenr => 0, :href => ""}],
  })
end

#add_member(node) ⇒ Object

Tries to place members into classes where they belong.

item with @member=Foo before we actually meet class Foo - in that case we register them as orphans. (Later when we finally meet class Foo, orphans are inserted into it.)

Items without @member belong by default to the preceding class. When no class precedes them - they too are orphaned.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/jsduck/aggregator.rb', line 121

def add_member(node)
  # Completely ignore member if @ignore used
  return if node[:meta][:ignore]

  if node[:owner]
    if @classes[node[:owner]]
      add_to_class(@classes[node[:owner]], node)
    else
      add_orphan(node)
    end
  elsif @current_class
    node[:owner] = @current_class[:name]
    add_to_class(@current_class, node)
  else
    add_orphan(node)
  end
end

#add_orphan(node) ⇒ Object



143
144
145
# File 'lib/jsduck/aggregator.rb', line 143

def add_orphan(node)
  @orphans << node
end

#add_to_class(cls, member) ⇒ Object



139
140
141
# File 'lib/jsduck/aggregator.rb', line 139

def add_to_class(cls, member)
  cls[:members] << member
end

#aggregate(file) ⇒ Object

Combines chunk of parsed JavaScript together with previously added chunks. The resulting documentation is accumulated inside this class and can be later accessed through #result method.

  • file SoureFile class instance



26
27
28
29
# File 'lib/jsduck/aggregator.rb', line 26

def aggregate(file)
  @current_class = nil
  file.each {|doc| register(doc) }
end

#append_ext4_event_optionsObject

Appends Ext4 options parameter to each event parameter list.



208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/jsduck/aggregator.rb', line 208

def append_ext4_event_options
  options = {
    :tagname => :param,
    :name => "eOpts",
    :type => "Object",
    :doc => "The options object passed to {@link Ext.util.Observable#addListener}."
  }
  @classes.each_value do |cls|
    cls[:members].each do |m|
      m[:params] << options if m[:tagname] == :event
    end
  end
end

#classify_orphansObject

Creates classes for orphans that have :owner property defined, and then inserts orphans to these classes.



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/jsduck/aggregator.rb', line 158

def classify_orphans
  @orphans.each do |orph|
    if orph[:owner]
      class_name = orph[:owner]
      if !@classes[class_name]
        # this will add the class and add all orphans to it
        add_empty_class(class_name)
      end
    end
  end
end

#create_accessorsObject

Creates accessor method for configs marked with @accessor



223
224
225
226
227
228
# File 'lib/jsduck/aggregator.rb', line 223

def create_accessors
  accessors = Accessors.new
  @classes.each_value do |cls|
    accessors.create(cls)
  end
end

#create_global_classObject

Creates class with name “global” and inserts all the remaining orphans into it (but only if there are any orphans).



172
173
174
175
176
177
178
179
180
181
# File 'lib/jsduck/aggregator.rb', line 172

def create_global_class
  return if @orphans.length == 0

  add_empty_class("global", "Global variables and functions.")
  @orphans.each do |orph|
    orph[:owner] = "global"
    add_member(orph)
  end
  @orphans = []
end

#ext4?Boolean

Are we dealing with ExtJS 4? True if any of the classes is defined with Ext.define()

Returns:

  • (Boolean)


248
249
250
# File 'lib/jsduck/aggregator.rb', line 248

def ext4?
  @documentation.any? {|cls| cls[:code_type] == :ext_define }
end

#insert_orphans(cls) ⇒ Object

Inserts available orphans to class



148
149
150
151
152
153
154
# File 'lib/jsduck/aggregator.rb', line 148

def insert_orphans(cls)
  members = @orphans.find_all {|node| node[:owner] == cls[:name] }
  members.each do |node|
    add_to_class(cls, node)
    @orphans.delete(node)
  end
end

#merge_classes(old, new) ⇒ Object

Merges new class-doc into old one.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/jsduck/aggregator.rb', line 88

def merge_classes(old, new)
  # Merge booleans
  [:extends, :singleton, :private].each do |tag|
    old[tag] = old[tag] || new[tag]
  end
  # Merge arrays
  [:mixins, :alternateClassNames, :files].each do |tag|
    old[tag] = old[tag] + new[tag]
  end
  # Merge meta hashes
  new[:meta].each_pair do |name, value|
    old[:meta][name] = old[:meta][name] || value
  end
  # Merge hashes of arrays
  [:aliases].each do |tag|
    new[tag].each_pair do |key, contents|
      old[tag][key] = (old[tag][key] || []) + contents
    end
  end
  old[:doc] = old[:doc].length > 0 ? old[:doc] : new[:doc]
  # Additionally the doc-comment can contain configs and constructor
  old[:members] += new[:members]
end

#process_enumsObject

Loops through all enums and auto-detects their types if needed.



231
232
233
# File 'lib/jsduck/aggregator.rb', line 231

def process_enums
  Enum.new(@classes).process_all!
end

#process_overridesObject

Processes all overrides. Returns list of override classes.



237
238
239
240
241
242
243
244
# File 'lib/jsduck/aggregator.rb', line 237

def process_overrides
  Override.new(@classes).process_all!.map do |cls|
    # discard each override class
    @classes.delete(cls[:name])
    @documentation.delete(cls)
    cls
  end
end

#register(node) ⇒ Object

Registers documentation node either as class or as member of some class.



33
34
35
36
37
38
39
# File 'lib/jsduck/aggregator.rb', line 33

def register(node)
  if node[:tagname] == :class
    add_class(node)
  else
    add_member(node)
  end
end

#remove_ignored_classesObject

Gets rid of classes marked with @ignore



198
199
200
201
202
203
204
205
# File 'lib/jsduck/aggregator.rb', line 198

def remove_ignored_classes
  @documentation.delete_if do |cls|
    if cls[:meta][:ignore]
      @classes.delete(cls["name"])
      true
    end
  end
end

#resultObject



252
253
254
# File 'lib/jsduck/aggregator.rb', line 252

def result
  @documentation + @orphans
end

#warn_alt_name(cls) ⇒ Object



81
82
83
84
85
# File 'lib/jsduck/aggregator.rb', line 81

def warn_alt_name(cls)
  file = cls[:files][0][:filename]
  line = cls[:files][0][:linenr]
  Logger.warn(:alt_name, "Name #{cls[:name]} used as both classname and alternate classname", file, line)
end