Skip to content

Instantly share code, notes, and snippets.

@bkad
Created August 19, 2016 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bkad/08d22f48bd6e1c769b9ab46cda9e23b6 to your computer and use it in GitHub Desktop.
Save bkad/08d22f48bd6e1c769b9ab46cda9e23b6 to your computer and use it in GitHub Desktop.
# Utility function to annotate CoffeeScript classes for Angular
_nextClassId = 0
isFunction = (thing) ->
typeof thing is "function"
isArray = (thing) ->
Array.isArray(thing)
stringify = (thing) ->
if typeof thing is "string"
thing
else if not thing?
"#{thing}"
else if thing.overriddenName
thing.overriddenName
else if thing.name
thing.name
else
res = thing.toString()
newLineIndex = res.indexOf("\n")
if newLineIndex is -1 then res else res.substring(0, newLineIndex)
extractAnnotation = (annotation) ->
if isFunction(annotation) and annotation.hasOwnProperty("annotation")
annotation.annotation
else
annotation
applyParams = (fnOrArray, key) ->
if isFunction(fnOrArray)
fnOrArray
else if isArray(fnOrArray)
[annotations..., fn] = fnOrArray
annoLength = annotations.length
if not isFunction(fn)
throw new Error("Last position of Class method array must be Function in key '#{key}' was #{stringify(fn)}")
if annoLength isnt fn.length
throw new Error("Number of annotations (#{annoLength}) does not match number of arguments (#{fn.length})
in the function: #{stringify(fn)}")
paramsAnnotations = []
for annotation in annotations
currAnnotations = []
paramsAnnotations.push(currAnnotations)
if isArray(annotation)
for subAnnotation in annotation
currAnnotations.push(extractAnnotation(subAnnotation))
else if isFunction(annotation)
currAnnotations.push(extractAnnotation(annotation))
else
currAnnotations.push(annotation)
Reflect.defineMetadata("parameters", paramsAnnotations, fn)
fn
else
throw new Error("Only Function or Array is supported in Class definition for key '#{key}' is '#{stringify(fnOrArray)}'")
module.exports = (coffeeClass) ->
proto = coffeeClass.prototype
parameters = proto.parameters ? []
applied = [parameters..., proto.constructor]
constructor = proto.constructor = applyParams(applied, "constructor")
unless constructor.name
constructor.overriddenName = "_anno_class#{_nextClassId++}"
if isArray(proto.annotations)
Reflect.defineMetadata("annotations", proto.annotations)
decorators = proto.decorators
if isArray(decorators)
callback = (accum, decorator) ->
decorator(accum)
constructor = decorators.reduceRight(callback, constructor)
constructor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment