Chromium Code Reviews| Index: lib/src/codegen/js_codegen.dart |
| diff --git a/lib/src/codegen/js_codegen.dart b/lib/src/codegen/js_codegen.dart |
| index 39b05cb6877099d2bbd4b4a575399ebb72cff31c..6bea151a7e60ed529ad6bb0313828d5d040e48e0 100644 |
| --- a/lib/src/codegen/js_codegen.dart |
| +++ b/lib/src/codegen/js_codegen.dart |
| @@ -56,7 +56,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| /// The variable for the current catch clause |
| SimpleIdentifier _catchParameter; |
| - ClassDeclaration currentClass; |
| ConstantEvaluator _constEvaluator; |
| final _exports = new Set<String>(); |
| @@ -323,8 +322,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| var jsName = getAnnotationValue(node, _isJsNameAnnotation); |
| if (jsName != null) return _emitJsType(node.name.name, jsName); |
| - currentClass = node; |
| - |
| var ctors = <ConstructorDeclaration>[]; |
| var fields = <FieldDeclaration>[]; |
| var staticFields = <FieldDeclaration>[]; |
| @@ -341,7 +338,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| var body = |
| _finishClassMembers(node.element, classExpr, ctors, staticFields); |
| - currentClass = null; |
| return _finishClassDef(type, body); |
| } |
| @@ -989,49 +985,55 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| /// going through the qualified library name if necessary. |
| @override |
| JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
| - var e = node.staticElement; |
| - if (e == null) { |
| + var accessor = node.staticElement; |
| + if (accessor == null) { |
| return js.commentExpression( |
| 'Unimplemented unknown name', new JS.Identifier(node.name)); |
| } |
| - var variable = e is PropertyAccessorElement ? e.variable : e; |
|
Jennifer Messerly
2015/04/16 22:50:30
"variable" was misleading ... this is just the "re
|
| - var name = variable.name; |
| + // Get the original declaring element. If we had a property accessor, this |
| + // indirects back to a (possibly synthetic) field. |
| + var element = accessor; |
| + if (element is PropertyAccessorElement) element = accessor.variable; |
|
Jennifer Messerly
2015/04/16 22:50:30
after this point we always use `element`.
|
| + var name = element.name; |
| // library member |
| - if (e.enclosingElement is CompilationUnitElement && |
| - (e.library != libraryInfo.library || |
| - variable is TopLevelVariableElement && !variable.isConst)) { |
| - return js.call('#.#', [_libraryName(e.library), name]); |
| + if (element.enclosingElement is CompilationUnitElement && |
| + (element.library != libraryInfo.library || |
| + element is TopLevelVariableElement && !element.isConst)) { |
| + return js.call('#.#', [_libraryName(element.library), name]); |
| } |
| - // instance member |
| - if (currentClass != null && _needsImplicitThis(e)) { |
| - return js.call( |
| - 'this.#', _emitMemberName(name, type: currentClass.element.type)); |
| - } |
| + // Unqualified class member. This could mean implicit-this, or implicit |
| + // call to a static from the same class. |
| + if (element is ClassMemberElement && element is! ConstructorElement) { |
| + bool isStatic = element.isStatic; |
| + var type = element.enclosingElement.type; |
| - // static member |
| - if (e is ExecutableElement && |
| - e.isStatic && |
| - variable.enclosingElement is ClassElement) { |
| - var className = (variable.enclosingElement as ClassElement).name; |
| - return js.call('#.#', [className, _emitMemberName(name, isStatic: true)]); |
| + // For instance methods, we add implicit-this. |
| + // For static methods, we add the raw type name, without generics or |
| + // library prefix. We don't need those because static calls can't use |
| + // the generic type. |
| + var target = isStatic ? new JS.Identifier(type.name) : new JS.This(); |
| + var member = _emitMemberName(name, isStatic: isStatic, type: type); |
| + return new JS.PropertyAccess(target, member); |
| } |
| // initializing formal parameter, e.g. `Point(this.x)` |
| - if (e is ParameterElement && e.isInitializingFormal && e.isPrivate) { |
| + if (element is ParameterElement && |
| + element.isInitializingFormal && |
| + element.isPrivate) { |
| /// Rename private names so they don't shadow the private field symbol. |
| /// The renamer would handle this, but it would prefer to rename the |
| /// temporary used for the private symbol. Instead rename the parameter. |
| - return _getTemp(e, '${name.substring(1)}'); |
| + return _getTemp(element, '${name.substring(1)}'); |
| } |
| - if (_isTemporary(e)) { |
| + if (_isTemporary(element)) { |
| if (name[0] == '#') { |
| return new JS.InterpolatedExpression(name.substring(1)); |
| } else { |
| - return _getTemp(e, name); |
| + return _getTemp(element, name); |
| } |
| } |
| @@ -2287,10 +2289,6 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| } |
| DartType getStaticType(Expression e) => rules.getStaticType(e); |
| - |
| - static bool _needsImplicitThis(Element e) => |
| - e is PropertyAccessorElement && !e.variable.isStatic || |
| - e is ClassMemberElement && !e.isStatic && e is! ConstructorElement; |
| } |
| class JSGenerator extends CodeGenerator { |