jashkenas/coffee-script — pull request #3237 by marchaefner (2013-11-12 16:17:53+00:00)
Title: Fix super-related tagging of `Code` nodes

* `super` compiles now in static methods with reserved names (#2949)
* `@fn: -> super` and `@fn = -> super` produce the same compilation (#3232)
* `super` will no longer compile for ambiguous / wrong super-targets (see Implications below)

#### Theory of Operation / Changes

`super` compiles only within a `Code` node that either

* is marked as a constructor (by `Class`)
* has both `.name` and `.klass` set
* has no own `.name` but is contained by another `Code` with both properties

If the `Code` node also has a truthy `.static` the super call will be compiled accordingly.

`.static` is set by `Class` for object assigns with a `@`. **Changed**: 97d9a63 looks also at non-object assignments. This fixes #3232.

`.klass` is set by

* `Class` to all its functions (on the class-level, not nested functions)
* `Assign` to prototype functions, i.e. if the LHS begins with the form {CLASS_NAME}.prototype.{IDENTIFIER|INDEX}. This has been **changed** to match only this exact form. (see also below)

`.name` is set by `Assign` which inspects its LHS with the help of the `METHOD_DEF` regexp. (Except constructors, they get their name from `Class.ensureConstructor`.)

**Changed**: 138c25f restricts `METHOD_DEF` to match only

* assignments to a prototype property, e.g. `C::f = ->`
But no longer to properties of objects on prototypes, e.g. `C::f.g = ->`
* assignments to a property of a possible class, e.g. `C.static = ->`
But no longer to anything else that ends with an IDENTIFIER, e.g. `C.a.b = ->`

Both cases are now detected in the same way. This fixes #2949.

#### Implications

The following examples do not work anymore and will throw a 'cannot call super ...' error. None of those look correct or useful to me.

```coffee
class Foo
bar = -> super
# bar = function() {
# return Foo.__super__.bar.apply(this, arguments);
# };

bar.baz.qux = -> super
# bar.baz.qux = function() {
# return Foo.__super__.qux.apply(this, arguments);
# };

# This (regrettably) still works
bar.baz = -> super

Foo::bar.baz = ->
# Foo.prototype.bar.baz = function() {
# return Foo.__super__.bar.apply(this, arguments);
# };
```

The following examples will no longer throw 'cannot call super ...' but compile. (This is related to #1606 -- but by no means complete or usable).

```coffee
class Foo
@bar: ->
baz = -> super
# return baz = function() {
# return Foo.__super__.constructor.bar.apply(this, arguments);
# };

Foo::bar = ->
baz = -> super
# return baz = function() {
# return Foo.__super__.bar.apply(this, arguments);
# };
```