File: src/com/google/javascript/jscomp/CheckGlobalThis.java
Issue: support @lends annotation
Some javascript toolkits (dojo, base, etc.) have a special way of declaring (what java calls) classes, for example in dojo:

dojo.declare("MyClass", [superClass1, superClass2], { 
    foo: function(){ ... } 
    bar: function(){ ... } 
}); 

JSDoc (or at least JSDoc toolkit) supports this via annotations: 

/** 
 * @name MyClass 
 * @class 
 * @extends superClass1 
 * @extends superClass2 
 */ 
dojo.declare("MyClass", [superClass1, superClass2], /** @lends 
MyClass.prototype */ { 
    foo: function(){ ... } 
    bar: function(){ ... } 
}); 

The @lends keyword in particular is useful since it tells JSDoc that foo and bar are part of MyClass's prototype.   But closure compiler isn't picking up on that, thus I get a bunch of errors about "dangerous use of this" inside of foo() and bar(). 

So, can @lends support be added to the closure compiler?

The workaround is to use @this on every method, but not sure if that is sufficient to make advanced mode compilation work correctly.

Buggy code:
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.getType() == Token.FUNCTION) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.isInterface() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {}; // or
    // var a = {x: function() {}};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN ||

          // object literal keys
          pType == Token.STRING ||
          pType == Token.NUMBER)) {
      return false;
    }

    // Don't traverse functions that are getting lent to a prototype.
  }

  if (parent != null && parent.getType() == Token.ASSIGN) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();

    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
      if (NodeUtil.isGet(lhs)) {
        if (lhs.getType() == Token.GETPROP &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        Node llhs = lhs.getFirstChild();
        if (llhs.getType() == Token.GETPROP &&
            llhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
      }
    }
  }

  return true;
}

Fixed code:
public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {

  if (n.getType() == Token.FUNCTION) {
    // Don't traverse functions that are constructors or have the @this
    // or @override annotation.
    JSDocInfo jsDoc = getFunctionJsDocInfo(n);
    if (jsDoc != null &&
        (jsDoc.isConstructor() ||
         jsDoc.isInterface() ||
         jsDoc.hasThisType() ||
         jsDoc.isOverride())) {
      return false;
    }

    // Don't traverse functions unless they would normally
    // be able to have a @this annotation associated with them. e.g.,
    // var a = function() { }; // or
    // function a() {} // or
    // a.x = function() {}; // or
    // var a = {x: function() {}};
    int pType = parent.getType();
    if (!(pType == Token.BLOCK ||
          pType == Token.SCRIPT ||
          pType == Token.NAME ||
          pType == Token.ASSIGN ||

          // object literal keys
          pType == Token.STRING ||
          pType == Token.NUMBER)) {
      return false;
    }

    // Don't traverse functions that are getting lent to a prototype.
    Node gramps = parent.getParent();
    if (NodeUtil.isObjectLitKey(parent, gramps)) {
      JSDocInfo maybeLends = gramps.getJSDocInfo();
      if (maybeLends != null &&
          maybeLends.getLendsName() != null &&
          maybeLends.getLendsName().endsWith(".prototype")) {
        return false;
      }
    }
  }

  if (parent != null && parent.getType() == Token.ASSIGN) {
    Node lhs = parent.getFirstChild();
    Node rhs = lhs.getNext();

    if (n == lhs) {
      // Always traverse the left side of the assignment. To handle
      // nested assignments properly (e.g., (a = this).property = c;),
      // assignLhsChild should not be overridden.
      if (assignLhsChild == null) {
        assignLhsChild = lhs;
      }
    } else {
      // Only traverse the right side if it's not an assignment to a prototype
      // property or subproperty.
      if (NodeUtil.isGet(lhs)) {
        if (lhs.getType() == Token.GETPROP &&
            lhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
        Node llhs = lhs.getFirstChild();
        if (llhs.getType() == Token.GETPROP &&
            llhs.getLastChild().getString().equals("prototype")) {
          return false;
        }
      }
    }
  }

  return true;
}