Commit 53d7469a authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Implement support for @override tag.

First off just a tag-based implementation of Ext4 overrides.
parent 1dfea528
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ require 'jsduck/class'
require 'jsduck/accessors'
require 'jsduck/logger'
require 'jsduck/enum'
require 'jsduck/override'

module JsDuck

@@ -231,6 +232,11 @@ module JsDuck
      Enum.new(@classes).process_all!
    end

    # Processes all overrides
    def process_overrides
      Override.new(@classes, @documentation).process_all!
    end

    # Are we dealing with ExtJS 4?
    # True if any of the classes is defined with Ext.define()
    def ext4?
+1 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ module JsDuck
        agr.append_ext4_event_options
      end
      agr.process_enums
      agr.process_overrides
      agr.result
    end

+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ module JsDuck
        :requires => detect_list(:requires, doc_map),
        :uses => detect_list(:uses, doc_map),
        :enum => detect_enum(doc_map),
        :override => extract(doc_map, :override, :class),
      }, doc_map)
    end

+10 −0
Original line number Diff line number Diff line
@@ -132,6 +132,8 @@ module JsDuck
          at_throws
        elsif look(/@enum\b/)
          at_enum
        elsif look(/@override\b/)
          at_override
        elsif look(/@inheritable\b/)
          boolean_at_tag(/@inheritable/, :inheritable)
        elsif look(/@accessor\b/)
@@ -294,6 +296,14 @@ module JsDuck
      skip_white
    end

    # matches @override name ...
    def at_override
      match(/@override/)
      add_tag(:override)
      maybe_ident_chain(:class)
      skip_white
    end

    # matches @type {type}  or  @type type
    #
    # The presence of @type implies that we are dealing with property.

lib/jsduck/override.rb

0 → 100644
+82 −0
Original line number Diff line number Diff line
module JsDuck

  class Override
    def initialize(classes_hash, classes_array)
      @classes_hash = classes_hash
      @classes_array = classes_array
    end

    # Applies all override classes to target classes
    def process_all!
      overrides = []

      @classes_array.each do |cls|
        if cls[:override]
          process(cls)
          overrides << cls
        end
      end

      # Discard override classes
      overrides.each do |cls|
        @classes_hash.delete(cls[:name])
        @classes_array.delete(cls)
      end
    end

    private

    # Applies override class to target class
    def process(override)
      target = @classes_hash[override[:override]]
      unless target
        ctx = override[:files][0]
        return Logger.instance.warn(:extend, "Class #{override[:override]} not found", ctx[:filename], ctx[:linenr])
      end

      # Combine comments of classes
      if override[:doc].length > 0
        target[:doc] += "\n\n**From override #{override[:name]}:** " + override[:doc]
      end
      target[:files] += override[:files]

      # Build lookup table of existing members
      existing = {}
      each_member(target) do |m|
        existing[m[:id]] = m
      end

      # When the same member exists in overridden class, just append
      # the docs.  Otherwise add the member as a whole to the class.
      each_member(override) do |m|
        ex = existing[m[:id]]
        if ex
          if m[:doc].length > 0
            ex[:doc] += "\n\n**From override #{override[:name]}:** " + m[:doc]
          else
            ex[:doc] += "\n\n**Overridden in #{override[:name]}.**"
          end
          ex[:files] += m[:files]
        else
          add_member(target, m)
          m[:doc] += "\n\n**Defined in override #{override[:name]}.**"
        end
      end
    end

    # helpers

    def each_member(cls)
      [:members, :statics].each do |category|
        cls[category].each_pair do |key, members|
          members.each {|m| yield m }
        end
      end
    end

    def add_member(cls, m)
      cls[m[:static] ? :statics : :members][m[:tagname]] << m
    end
  end

end
Loading