Skip to content

Commit

Permalink
Add support for Java classes implementing/overriding @JsProperty meth…
Browse files Browse the repository at this point in the history
…ods.

Change-Id: I6d7a6c59c1b038efd11bd18484ec0feacd496736
  • Loading branch information
rluble committed Oct 13, 2015
1 parent 97a4312 commit a8bd429
Show file tree
Hide file tree
Showing 19 changed files with 633 additions and 448 deletions.
19 changes: 16 additions & 3 deletions dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
Expand Up @@ -51,15 +51,28 @@ public enum JsPropertyAccessorType {
/** /**
* A getter property accessor. Usually in the form of getX()/isX(). * A getter property accessor. Usually in the form of getX()/isX().
*/ */
GETTER, GETTER("get"),
/** /**
* A setter property accessor. Usually in the form of setX(x). * A setter property accessor. Usually in the form of setX(x).
*/ */
SETTER, SETTER("set"),
/** /**
* A property accessor but doesn't match setter/getter patterns. * A property accessor but doesn't match setter/getter patterns.
*/ */
UNDEFINED, UNDEFINED;

private String key;

JsPropertyAccessorType() {
}

JsPropertyAccessorType(String key) {
this.key = key;
}

public String getKey() {
return key;
}
} }


public static final Comparator<JMethod> BY_SIGNATURE_COMPARATOR = new Comparator<JMethod>() { public static final Comparator<JMethod> BY_SIGNATURE_COMPARATOR = new Comparator<JMethod>() {
Expand Down
128 changes: 82 additions & 46 deletions dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
Expand Up @@ -64,6 +64,7 @@
import com.google.gwt.dev.jjs.ast.JLocalRef; import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMember; import com.google.gwt.dev.jjs.ast.JMember;
import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethod.JsPropertyAccessorType;
import com.google.gwt.dev.jjs.ast.JMethodBody; import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall; import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNameOf; import com.google.gwt.dev.jjs.ast.JNameOf;
Expand Down Expand Up @@ -142,7 +143,6 @@
import com.google.gwt.dev.js.ast.JsPostfixOperation; import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation; import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram; import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
import com.google.gwt.dev.js.ast.JsReturn; import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsRootScope; import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope; import com.google.gwt.dev.js.ast.JsScope;
Expand Down Expand Up @@ -190,7 +190,6 @@
* Creates a JavaScript AST from a <code>JProgram</code> node. * Creates a JavaScript AST from a <code>JProgram</code> node.
*/ */
public class GenerateJavaScriptAST { public class GenerateJavaScriptAST {

/** /**
* Finds the nodes that are targets of JNameOf so that a name is assigned to them. * Finds the nodes that are targets of JNameOf so that a name is assigned to them.
*/ */
Expand Down Expand Up @@ -368,7 +367,7 @@ public boolean visit(JMethod x, Context ctx) {
} else if (x.isPackagePrivate()) { } else if (x.isPackagePrivate()) {
polyName = interfaceScope.declareName(mangleNameForPackagePrivatePoly(x), name); polyName = interfaceScope.declareName(mangleNameForPackagePrivatePoly(x), name);
} else { } else {
boolean isJsMethod = x.isOrOverridesJsMethod() && !x.isJsPropertyAccessor(); boolean isJsMethod = x.isOrOverridesJsMethod();
polyName = polyName =
isJsMethod isJsMethod
? interfaceScope.declareUnobfuscatableName(x.getJsName()) ? interfaceScope.declareUnobfuscatableName(x.getJsName())
Expand Down Expand Up @@ -520,9 +519,20 @@ private <T extends HasEnclosingType & HasName & HasSourceInfo> void recordSymbol


private class GenerateJavaScriptTransformer extends JTransformer<JsNode> { private class GenerateJavaScriptTransformer extends JTransformer<JsNode> {


public static final String GOOG_INHERITS = "goog.inherits";
public static final String GOOG_ABSTRACT_METHOD = "goog.abstractMethod"; public static final String GOOG_ABSTRACT_METHOD = "goog.abstractMethod";
public static final String GOOG_INHERITS = "goog.inherits";
public static final String GOOG_OBJECT_CREATE_SET = "goog.object.createSet"; public static final String GOOG_OBJECT_CREATE_SET = "goog.object.createSet";
public static final String JCHSU = "JavaClassHierarchySetupUtil";
public static final String JCHSU_COPY_OBJECT_PROPERTIES = JCHSU + ".copyObjectProperties";
public static final String JCHSU_DEFINE_CLASS = JCHSU + ".defineClass";
public static final String JCHSU_DEFINE_PROPERTIES = JCHSU + ".defineProperties";
public static final String JCHSU_EMPTY_METHOD = JCHSU + ".emptyMethod";
public static final String JCHSU_GET_CLASS_PROTOTYPE = JCHSU + ".getClassPrototype";
public static final String JCHSU_MAKE_LAMBDA_FUNCTION = JCHSU + ".makeLambdaFunction";
public static final String JCHSU_MODERNIZE_BROWSER = JCHSU + ".modernizeBrowser";
public static final String JCHSU_TYPE_MARKER_FN = JCHSU + ".typeMarkerFn";
public static final String OBJECT_TYPEMARKER = "Object.typeMarker";

private final Set<JDeclaredType> alreadyRan = Sets.newLinkedHashSet(); private final Set<JDeclaredType> alreadyRan = Sets.newLinkedHashSet();


private final Map<String, Object> exportedMembersByExportName = new TreeMap<String, Object>(); private final Map<String, Object> exportedMembersByExportName = new TreeMap<String, Object>();
Expand Down Expand Up @@ -946,7 +956,7 @@ private JsExpression getPrototypeQualifierViaLookup(JDeclaredType type, SourceIn
// TODO(rluble): Ideally we would want to construct the inheritance chain the JS way and // TODO(rluble): Ideally we would want to construct the inheritance chain the JS way and
// then we could do Type.prototype.polyname.call(this, ...). Currently prototypes do not // then we could do Type.prototype.polyname.call(this, ...). Currently prototypes do not
// have global names instead they are stuck into the prototypesByTypeId array. // have global names instead they are stuck into the prototypesByTypeId array.
return constructInvocation(sourceInfo, "JavaClassHierarchySetupUtil.getClassPrototype", return constructInvocation(sourceInfo, JCHSU_GET_CLASS_PROTOTYPE,
(JsExpression) transform(getRuntimeTypeReference(type))); (JsExpression) transform(getRuntimeTypeReference(type)));
} }
} }
Expand All @@ -958,20 +968,11 @@ private JsExpression dispatchToJsFunction(


private JsExpression dispatchToInstanceMethod( private JsExpression dispatchToInstanceMethod(
JsExpression instance, JMethod method, List<JsExpression> args, SourceInfo sourceInfo) { JsExpression instance, JMethod method, List<JsExpression> args, SourceInfo sourceInfo) {
JsNameRef reference = JsNameRef reference = polymorphicNames.get(method).makeQualifiedRef(sourceInfo, instance);
method.isJsPropertyAccessor()
? new JsNameRef(sourceInfo, method.getJsName())
: polymorphicNames.get(method).makeRef(sourceInfo);
reference.setQualifier(instance);


switch (method.getJsPropertyAccessorType()) { JsPropertyAccessorType propertyAccessorType = method.getJsPropertyAccessorType();
case SETTER: return JsUtils
return createAssignment(reference, args.get(0)); .createInvocationOrPropertyAccess(sourceInfo, propertyAccessorType, reference, args);
case GETTER:
return reference;
default:
return new JsInvocation(sourceInfo, reference, args);
}
} }


@Override @Override
Expand Down Expand Up @@ -1012,6 +1013,7 @@ public JsNode transformNewInstance(JNewInstance newInstance) {
if (newInstance.getClassType().isJsFunctionImplementation()) { if (newInstance.getClassType().isJsFunctionImplementation()) {
return constructJsFunctionObject(sourceInfo, newInstance.getClassType(), ctorName, newExpr); return constructJsFunctionObject(sourceInfo, newInstance.getClassType(), ctorName, newExpr);
} }

return newExpr; return newExpr;
} }


Expand All @@ -1023,8 +1025,7 @@ private JsNode constructJsFunctionObject(SourceInfo sourceInfo, JClassType type,
ctorName, prototype, polymorphicNames.get(jsFunctionMethod)); ctorName, prototype, polymorphicNames.get(jsFunctionMethod));


// makeLambdaFunction(Foo.prototype.functionMethodName, new Foo(...)) // makeLambdaFunction(Foo.prototype.functionMethodName, new Foo(...))
return constructInvocation(sourceInfo, "JavaClassHierarchySetupUtil.makeLambdaFunction", return constructInvocation(sourceInfo, JCHSU_MAKE_LAMBDA_FUNCTION, funcNameRef, newExpr);
funcNameRef, newExpr);
} }


private JMethod getJsFunctionMethod(JClassType type) { private JMethod getJsFunctionMethod(JClassType type) {
Expand Down Expand Up @@ -1242,9 +1243,8 @@ private Set<JDeclaredType> generatePreamble(JProgram program) {


// Perform necessary polyfills. // Perform necessary polyfills.
addTypeDefinitionStatement( addTypeDefinitionStatement(
program.getIndexedType("JavaClassHierarchySetupUtil"), program.getIndexedType(JCHSU),
constructInvocation( constructInvocation(program.getSourceInfo(), JCHSU_MODERNIZE_BROWSER).makeStmt());
program.getSourceInfo(), "JavaClassHierarchySetupUtil.modernizeBrowser").makeStmt());


Set<JDeclaredType> alreadyProcessed = Set<JDeclaredType> alreadyProcessed =
Sets.<JDeclaredType>newLinkedHashSet(program.immortalCodeGenTypes); Sets.<JDeclaredType>newLinkedHashSet(program.immortalCodeGenTypes);
Expand Down Expand Up @@ -1601,8 +1601,7 @@ public void endVisit(JsNameRef x, JsContext ctx) {
if (jsName == null) { if (jsName == null) {
// this can occur when JSNI references an instance method on a // this can occur when JSNI references an instance method on a
// type that was never actually instantiated. // type that was never actually instantiated.
jsName = jsName = indexedFunctions.get(JCHSU_EMPTY_METHOD).getName();
indexedFunctions.get("JavaClassHierarchySetupUtil.emptyMethod").getName();
} }
x.resolve(jsName); x.resolve(jsName);
} }
Expand Down Expand Up @@ -1658,14 +1657,13 @@ private JsExpression buildJsCastMapLiteral(List<JsExpression> runtimeTypeIdLiter
return buildClosureStyleCastMapFromArrayLiteral(runtimeTypeIdLiterals, sourceInfo); return buildClosureStyleCastMapFromArrayLiteral(runtimeTypeIdLiterals, sourceInfo);
} }


JsObjectLiteral objectLiteral = new JsObjectLiteral(sourceInfo);
objectLiteral.setInternable();
List<JsPropertyInitializer> initializers = objectLiteral.getPropertyInitializers();
JsNumberLiteral one = new JsNumberLiteral(sourceInfo, 1); JsNumberLiteral one = new JsNumberLiteral(sourceInfo, 1);
JsObjectLiteral.Builder objectLiteralBuilder = JsObjectLiteral.builder(sourceInfo)
.setInternable();
for (JsExpression runtimeTypeIdLiteral : runtimeTypeIdLiterals) { for (JsExpression runtimeTypeIdLiteral : runtimeTypeIdLiterals) {
initializers.add(new JsPropertyInitializer(sourceInfo, runtimeTypeIdLiteral, one)); objectLiteralBuilder.add(runtimeTypeIdLiteral, one);
} }
return objectLiteral; return objectLiteralBuilder.build();
} }


private JsExpression buildClosureStyleCastMapFromArrayLiteral( private JsExpression buildClosureStyleCastMapFromArrayLiteral(
Expand Down Expand Up @@ -2005,13 +2003,13 @@ private void generateCallToDefineClass(JClassType type, List<JsNameRef> construc


// JavaClassHierarchySetupUtil.defineClass(typeId, superTypeId, castableMap, constructors) // JavaClassHierarchySetupUtil.defineClass(typeId, superTypeId, castableMap, constructors)
JsStatement defineClassStatement = constructInvocation(type.getSourceInfo(), JsStatement defineClassStatement = constructInvocation(type.getSourceInfo(),
"JavaClassHierarchySetupUtil.defineClass", defineClassArguments).makeStmt(); JCHSU_DEFINE_CLASS, defineClassArguments).makeStmt();
addTypeDefinitionStatement(type, defineClassStatement); addTypeDefinitionStatement(type, defineClassStatement);


if (jsPrototype != null) { if (jsPrototype != null) {
JsStatement statement = JsStatement statement =
constructInvocation(type.getSourceInfo(), constructInvocation(type.getSourceInfo(),
"JavaClassHierarchySetupUtil.copyObjectProperties", JCHSU_COPY_OBJECT_PROPERTIES,
getPrototypeQualifierViaLookup(program.getTypeJavaLangObject(), type.getSourceInfo()), getPrototypeQualifierViaLookup(program.getTypeJavaLangObject(), type.getSourceInfo()),
globalTemp.makeRef(type.getSourceInfo())) globalTemp.makeRef(type.getSourceInfo()))
.makeStmt(); .makeStmt();
Expand Down Expand Up @@ -2144,7 +2142,7 @@ private void generateInlinedDefineClass(JDeclaredType type, JsName classVar) {
if (jsPrototype != null) { if (jsPrototype != null) {
JsStatement statement = JsStatement statement =
constructInvocation(info, constructInvocation(info,
"JavaClassHierarchySetupUtil.copyObjectProperties", JCHSU_COPY_OBJECT_PROPERTIES,
getPrototypeQualifierOf(program.getTypeJavaLangObject(), info), getPrototypeQualifierOf(program.getTypeJavaLangObject(), info),
getPrototypeQualifierOf(type, info)).makeStmt(); getPrototypeQualifierOf(type, info)).makeStmt();
addTypeDefinitionStatement(type, statement); addTypeDefinitionStatement(type, statement);
Expand All @@ -2157,9 +2155,8 @@ private void setupCastMapOnPrototype(JDeclaredType type) {
} }


private void setupTypeMarkerOnJavaLangObjectPrototype(JDeclaredType type) { private void setupTypeMarkerOnJavaLangObjectPrototype(JDeclaredType type) {
JsFunction typeMarkerMethod = indexedFunctions.get( JsFunction typeMarkerMethod = indexedFunctions.get(JCHSU_TYPE_MARKER_FN);
"JavaClassHierarchySetupUtil.typeMarkerFn"); generatePrototypeAssignmentForJavaField(type, OBJECT_TYPEMARKER,
generatePrototypeAssignmentForJavaField(type, "Object.typeMarker",
typeMarkerMethod.getName().makeRef(type.getSourceInfo())); typeMarkerMethod.getName().makeRef(type.getSourceInfo()));
} }


Expand Down Expand Up @@ -2231,14 +2228,52 @@ private void maybeGenerateToStringAlias(JDeclaredType type) {
} }
} }


/** private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs) {
* Create a vtable assignment of the form _.polyname = rhs; and register the line as generatePrototypeAssignment(method, name, rhs, method.getJsPropertyAccessorType());
* created for {@code method}. }
*/
private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs) { /**
* Create a vtable assignment of the form _.polyname = rhs; and register the line as
* created for {@code method}.
*/
private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs,
JsPropertyAccessorType accessorType) {
SourceInfo sourceInfo = method.getSourceInfo(); SourceInfo sourceInfo = method.getSourceInfo();
JsNameRef lhs = name.makeQualifiedRef(sourceInfo, getPrototypeQualifierOf(method)); JsNameRef prototypeQualifierOf = getPrototypeQualifierOf(method);
emitMethodImplementation(method, lhs, createAssignment(lhs, rhs).makeStmt()); JsNameRef lhs = name.makeQualifiedRef(sourceInfo, prototypeQualifierOf);
switch (accessorType) {
case GETTER:
case SETTER:
emitPropertyImplementation(method, prototypeQualifierOf, name.makeRef(sourceInfo), rhs);
break;
default:
emitMethodImplementation(method, lhs, createAssignment(lhs, rhs).makeStmt());
break;
}
}

private void emitPropertyImplementation(JMethod method, JsNameRef prototype, JsNameRef name,
JsExpression methodDefinitionStatement) {
SourceInfo sourceInfo = method.getSourceInfo();

// We use Object.defineProperties instead of Object.defineProperty to make sure the
// property name appears as an identifier and not as a string.
// Some JS optimizers, e.g. the closure compiler, relies on this subtle difference for
// obfuscating property names.
JsNameRef definePropertyMethod =
indexedFunctions.get(JCHSU_DEFINE_PROPERTIES).getName().makeRef(sourceInfo);

JsObjectLiteral definePropertyLiteral =
JsObjectLiteral.builder(sourceInfo)
// {name: {get: function() { ..... }} or {set : function (v) {....}}}
.add(name, JsObjectLiteral.builder(sourceInfo)
// {get: function() { ..... }} or {set : function (v) {....}}
.add(method.getJsPropertyAccessorType().getKey(), methodDefinitionStatement)
.build())
.build();

addMethodDefinitionStatement(method, new JsInvocation(sourceInfo, definePropertyMethod,
prototype, definePropertyLiteral).makeStmt());
} }


private void emitMethodImplementation(JMethod method, JsNameRef functionNameRef, private void emitMethodImplementation(JMethod method, JsNameRef functionNameRef,
Expand All @@ -2255,14 +2290,15 @@ private void generatePrototypeDefinitionAlias(JMethod method, JsName alias) {
JsName polyName = polymorphicNames.get(method); JsName polyName = polymorphicNames.get(method);
JsExpression bridge = JsUtils.createBridge(method, polyName, topScope); JsExpression bridge = JsUtils.createBridge(method, polyName, topScope);
// Aliases are never property accessors. // Aliases are never property accessors.
generatePrototypeAssignment(method, alias, bridge); generatePrototypeAssignment(method, alias, bridge, JsPropertyAccessorType.NONE);
} }


private JsExprStmt outputDisplayName(JsNameRef function, JMethod method) { private JsExprStmt outputDisplayName(JsNameRef function, JMethod method) {
JsNameRef displayName = new JsNameRef(function.getSourceInfo(), "displayName"); JsNameRef displayName = new JsNameRef(function.getSourceInfo(), "displayName");
displayName.setQualifier(function); displayName.setQualifier(function);
String displayStringName = getDisplayName(method); String displayStringName = getDisplayName(method);
JsStringLiteral displayMethodName = new JsStringLiteral(function.getSourceInfo(), displayStringName); JsStringLiteral displayMethodName =
new JsStringLiteral(function.getSourceInfo(), displayStringName);
return createAssignment(displayName, displayMethodName).makeStmt(); return createAssignment(displayName, displayMethodName).makeStmt();
} }


Expand Down Expand Up @@ -2407,7 +2443,7 @@ private void handleClinit(JDeclaredType type, JsFunction clinitFunction) {
// provides a better debug experience that does not step into already used clinits. // provides a better debug experience that does not step into already used clinits.


JsFunction emptyFunctionFn = incremental ? objectConstructorFunction JsFunction emptyFunctionFn = incremental ? objectConstructorFunction
: indexedFunctions.get("JavaClassHierarchySetupUtil.emptyMethod"); : indexedFunctions.get(JCHSU_EMPTY_METHOD);
JsExpression assignment = createAssignment(clinitFunction.getName().makeRef(sourceInfo), JsExpression assignment = createAssignment(clinitFunction.getName().makeRef(sourceInfo),
emptyFunctionFn.getName().makeRef(sourceInfo)); emptyFunctionFn.getName().makeRef(sourceInfo));
statements.add(0, assignment.makeStmt()); statements.add(0, assignment.makeStmt());
Expand Down
4 changes: 2 additions & 2 deletions dev/core/src/com/google/gwt/dev/js/CoverageInstrumentor.java
Expand Up @@ -74,9 +74,9 @@ public static void exec(JsProgram jsProgram, Multimap<String, Integer> instrumen
@VisibleForTesting @VisibleForTesting
static JsObjectLiteral baselineCoverage(SourceInfo info, static JsObjectLiteral baselineCoverage(SourceInfo info,
Multimap<String, Integer> instrumentableLines) { Multimap<String, Integer> instrumentableLines) {
JsObjectLiteral.Builder baselineBuilder = JsObjectLiteral.builder().setSourceInfo(info); JsObjectLiteral.Builder baselineBuilder = JsObjectLiteral.builder(info);
for (String filename : instrumentableLines.keySet()) { for (String filename : instrumentableLines.keySet()) {
JsObjectLiteral.Builder linesBuilder = JsObjectLiteral.builder().setSourceInfo(info); JsObjectLiteral.Builder linesBuilder = JsObjectLiteral.builder(info);
for (int line : instrumentableLines.get(filename)) { for (int line : instrumentableLines.get(filename)) {
linesBuilder.add(new JsNumberLiteral(info, line), new JsNumberLiteral(info, 0)); linesBuilder.add(new JsNumberLiteral(info, line), new JsNumberLiteral(info, 0));
} }
Expand Down
4 changes: 2 additions & 2 deletions dev/core/src/com/google/gwt/dev/js/JsParser.java
Expand Up @@ -844,8 +844,8 @@ private JsExpression mapNumber(Node numberNode) {
} }


private JsExpression mapObjectLit(Node objLitNode) throws JsParserException { private JsExpression mapObjectLit(Node objLitNode) throws JsParserException {
JsObjectLiteral.Builder objectLiteralBuilder = JsObjectLiteral.builder() JsObjectLiteral.Builder objectLiteralBuilder =
.setSourceInfo(makeSourceInfo(objLitNode)); JsObjectLiteral.builder(makeSourceInfo(objLitNode));
Node fromPropInit = objLitNode.getFirstChild(); Node fromPropInit = objLitNode.getFirstChild();
while (fromPropInit != null) { while (fromPropInit != null) {


Expand Down
25 changes: 23 additions & 2 deletions dev/core/src/com/google/gwt/dev/js/JsUtils.java
Expand Up @@ -17,6 +17,7 @@


import com.google.gwt.dev.jjs.SourceInfo; import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethod.JsPropertyAccessorType;
import com.google.gwt.dev.jjs.ast.JParameter; import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType; import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.js.ast.JsBinaryOperation; import com.google.gwt.dev.js.ast.JsBinaryOperation;
Expand All @@ -35,6 +36,9 @@
import com.google.gwt.dev.js.ast.JsStatement; import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsThisRef; import com.google.gwt.dev.js.ast.JsThisRef;
import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import java.util.List;


/** /**
* Utils for JS AST. * Utils for JS AST.
Expand Down Expand Up @@ -94,11 +98,14 @@ public static JsFunction createBridge(JMethod method, JsName polyName, JsScope s
} }
JsNameRef ref = polyName.makeRef(sourceInfo); JsNameRef ref = polyName.makeRef(sourceInfo);
ref.setQualifier(new JsThisRef(sourceInfo)); ref.setQualifier(new JsThisRef(sourceInfo));
JsInvocation invocation = new JsInvocation(sourceInfo, ref); List<JsExpression> args = Lists.newArrayList();
for (JsParameter p : bridge.getParameters()) { for (JsParameter p : bridge.getParameters()) {
invocation.getArguments().add(p.getName().makeRef(sourceInfo)); args.add(p.getName().makeRef(sourceInfo));
} }


JsExpression invocation =
createInvocationOrPropertyAccess(sourceInfo, method.getJsPropertyAccessorType(), ref, args);

JsBlock block = new JsBlock(sourceInfo); JsBlock block = new JsBlock(sourceInfo);
if (method.getType() == JPrimitiveType.VOID) { if (method.getType() == JPrimitiveType.VOID) {
block.getStatements().add(invocation.makeStmt()); block.getStatements().add(invocation.makeStmt());
Expand Down Expand Up @@ -150,6 +157,20 @@ public static JsNameRef createQualifiedNameRef(SourceInfo info, JsName... names
return result; return result;
} }


public static JsExpression createInvocationOrPropertyAccess(SourceInfo sourceInfo,
JsPropertyAccessorType propertyAccessorType, JsNameRef reference, List<JsExpression> args) {
switch (propertyAccessorType) {
case SETTER:
assert args.size() == 1;
return createAssignment(reference, args.get(0));
case GETTER:
assert args.size() == 0;
return reference;
default:
return new JsInvocation(sourceInfo, reference, args);
}
}

/** /**
* Given a string qualifier such as 'foo.bar.Baz', returns a chain of JsNameRef's representing * Given a string qualifier such as 'foo.bar.Baz', returns a chain of JsNameRef's representing
* this qualifier. * this qualifier.
Expand Down

0 comments on commit a8bd429

Please sign in to comment.