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.



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

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.



41
42
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
# File 'lib/jsduck/aggregator.rb', line 41

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



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

def add_empty_class(name, doc = "")
  add_class({
    :tagname => :class,
    :name => name,
    :doc => doc,
    :mixins => [],
    :alternateClassNames => [],
    :members => Class.default_members_hash,
    :statics => Class.default_members_hash,
    :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.



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

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



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

def add_orphan(node)
  @orphans << node
end

#add_to_class(cls, member) ⇒ Object



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

def add_to_class(cls, member)
  cls[member[:meta][:static] ? :statics : :members][member[:tagname]] << 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



24
25
26
27
# File 'lib/jsduck/aggregator.rb', line 24

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. But only when we are dealing with Ext4 codebase.



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

def append_ext4_event_options
  return unless ext4?

  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][:event].each {|e| e[:params] << options }
  end
end

#classify_orphansObject

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



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

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



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

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).



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

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)


233
234
235
# File 'lib/jsduck/aggregator.rb', line 233

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

#insert_orphans(cls) ⇒ Object

Inserts available orphans to class



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

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.



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

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][:cfg] += new[:members][:cfg]
  old[:members][:method] += new[:members][:method]
end

#register(node) ⇒ Object

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



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

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



237
238
239
# File 'lib/jsduck/aggregator.rb', line 237

def result
  @documentation + @orphans
end

#warn_alt_name(cls) ⇒ Object



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

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