codo
Version:
A CoffeeScript documentation generator.
242 lines (190 loc) • 6.86 kB
text/coffeescript
Entity = require '../entity'
Method = require './method'
Variable = require './variable'
Property = require './property'
Mixin = require './mixin'
MetaMethod = require '../meta/method'
Entities = require '../_entities'
Winston = require 'winston'
module.exports = class Entities.Class extends Entity
= "Class"
: (node) ->
node.constructor.name is 'Class' && node.variable?.base?.value?
constructor: (, , ) ->
[, ] =
= if .parent
= .documentation
=
= []
= []
= []
= []
= []
= []
= []
name = .split('.')
= name.pop()
= ?.namespace or name.join('.')
if .options.debug
Winston.info "Creating new Class Entity"
Winston.info " name: " +
Winston.info " documentation: " +
@
# Determines if the class definition at given node is using
# and if in such case this class is nested into another one
determineContainment: (node) ->
if node.base?.value == 'this'
selfish = true # class
container = # class Foo \n class
[selfish, container]
fetchParent: (source) ->
[selfish, container] =
fetchName: (source, selfish, container) ->
name = []
# Nested class definition inherits
# the namespace from the containing class
name.push container.name if container
# Take the actual name of assignation unless
# we are prefixed with `@`
name.push source.base.value if !selfish && source.base?
# Get the rest of actual assignation path
if source.properties
name.push prop.name.value for prop in source.properties when prop.name?
# Here comes the magic!
name.join('.')
linkify: ->
super
for node in .body.expressions
if node.constructor.name == 'Assign' && node.entities?
if node.constructor.name == 'Value'
if node.constructor.name == 'Call' && node.entities?
linkifyAssign: (node) ->
for entity in node.entities when entity.selfish
# class Foo
# = ->
if entity instanceof Method
entity.kind = 'static'
.push entity
# class Foo
# = 'test'
if entity instanceof Variable
entity.kind = 'static'
.push entity
linkifyValue: (node) ->
for property in node.base.properties when property.entities?
for entity in property.entities
# class Foo
# : ->
# foo: ->
if entity instanceof Method
entity.kind = if entity.selfish then 'static' else 'dynamic'
.push entity
# class Foo
# foo: 'test'
if entity instanceof Variable
entity.kind = if entity.selfish then 'static' else 'dynamic'
.push entity
if entity instanceof Property
.push entity
linkifyCall: (node) ->
for entity in node.entities
if entity instanceof Property
found = false
for property in
if property.name == entity.name
entity.unite(property)
found = true
.push(entity) unless found
linkifyParent: ->
if
= .find(Class, ) ||
.descendants?.push(@)
linkifyMixins: ->
if ?.includes?
for entry in .includes
mixin = .find(Mixin, entry) || entry
.push(mixin)
mixin.inclusions?.push(@)
if ?.extends?
for entry in .extends
mixin = .find(Mixin, entry) || entry
.push(mixin)
mixin.extensions?.push(@)
if ?.concerns?
for entry in .concerns
mixin = .find(Mixin, entry) || entry
.push(mixin)
mixin.concerns?.push(@)
effectiveMethods: ->
return if ?
= []
for method in
.push(MetaMethod.fromMethodEntity method)
if ?.methods
for method in .methods
.push(MetaMethod.fromDocumentationMethod method)
allMethods: ->
methods = .map (method) =>
{
entity: method
owner: @
}
resolvers =
includes: 'effectiveInclusionMethods'
extends: 'effectiveExtensionMethods'
concerns: 'effectiveConcernMethods'
for storage, resolver of resolvers
for mixin in @[storage]
if mixin[resolver]
for method in mixin[resolver]()
methods.push
entity: method
owner: mixin
methods
inherited: (getter) ->
return [] if ! || !.name?
found = {}
entries = getter()
entries.filter (entry) ->
found[entry.entity.name] = true unless found[entry.entity.name]
inheritedMethods: ->
||= =>
.allMethods().concat .inheritedMethods()
inheritedVariables: ->
||= =>
variables = .variables.map (variable) =>
{
entity: variable
owner:
}
variables.concat .inheritedVariables()
inheritedProperties: ->
||= =>
properties = .properties.map (property) =>
{
entity: property
owner:
}
properties.concat .inheritedProperties()
inspect: ->
{
file: .path
documentation: ?.inspect()
selfish:
name:
container: ?.inspect()
parent: ?.inspect?() ||
methods: .map (x) -> x.inspect()
variables: .map (x) -> x.inspect()
properties: .map (x) -> x.inspect()
includes: .map (x) -> x.inspect?() || x
extends: .map (x) -> x.inspect?() || x
concerns: .map (x) -> x.inspect?() || x
}