From 64e3270a9a02eea66fb9beab9e423a14f60b6cec Mon Sep 17 00:00:00 2001 From: Goktug Gokdogan Date: Tue, 3 Nov 2015 19:13:27 -0800 Subject: [PATCH] Refactor property/member identification for JsInterop. Change-Id: I7e4d2bc0675bb08f013c69993c1fd602f12a8ca1 --- .../google/gwt/dev/javac/JsInteropUtil.java | 91 ++++---- .../com/google/gwt/dev/jjs/ast/HasJsInfo.java | 104 ++++++++- .../google/gwt/dev/jjs/ast/JDeclaredType.java | 19 +- .../com/google/gwt/dev/jjs/ast/JField.java | 20 +- .../com/google/gwt/dev/jjs/ast/JMember.java | 2 +- .../com/google/gwt/dev/jjs/ast/JMethod.java | 138 +++--------- .../gwt/dev/jjs/impl/ControlFlowAnalyzer.java | 4 +- .../gwt/dev/jjs/impl/ControlFlowRecorder.java | 2 +- .../dev/jjs/impl/GenerateJavaScriptAST.java | 45 ++-- .../com/google/gwt/dev/jjs/impl/JjsUtils.java | 2 +- .../jjs/impl/JsInteropRestrictionChecker.java | 200 +++++++----------- .../jjs/impl/SameParameterValueOptimizer.java | 2 +- .../gwt/dev/jjs/impl/TypeTightener.java | 2 +- .../com/google/gwt/dev/jjs/impl/UnifyAst.java | 2 +- .../src/com/google/gwt/dev/js/JsUtils.java | 8 +- .../impl/JsInteropRestrictionCheckerTest.java | 45 ++-- 16 files changed, 332 insertions(+), 354 deletions(-) diff --git a/dev/core/src/com/google/gwt/dev/javac/JsInteropUtil.java b/dev/core/src/com/google/gwt/dev/javac/JsInteropUtil.java index f04627ae944..87dd8452e5d 100644 --- a/dev/core/src/com/google/gwt/dev/javac/JsInteropUtil.java +++ b/dev/core/src/com/google/gwt/dev/javac/JsInteropUtil.java @@ -15,6 +15,7 @@ */ package com.google.gwt.dev.javac; +import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType; import com.google.gwt.dev.jjs.ast.JClassType; import com.google.gwt.dev.jjs.ast.JConstructor; import com.google.gwt.dev.jjs.ast.JDeclaredType; @@ -22,9 +23,7 @@ import com.google.gwt.dev.jjs.ast.JInterfaceType; import com.google.gwt.dev.jjs.ast.JMember; import com.google.gwt.dev.jjs.ast.JMethod; -import com.google.gwt.dev.jjs.ast.JMethod.JsPropertyAccessorType; import com.google.gwt.dev.jjs.ast.JPrimitiveType; -import com.google.gwt.thirdparty.guava.common.base.Strings; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; @@ -46,7 +45,7 @@ public final class JsInteropUtil { public static void maybeSetJsInteropProperties(JDeclaredType type, Annotation... annotations) { AnnotationBinding jsType = JdtUtil.getAnnotation(annotations, JSTYPE_CLASS); String namespace = maybeGetJsNamespace(annotations); - String exportName = maybeGetJsExportName(annotations, ""); + String exportName = maybeGetJsExportName(annotations); String jsPrototype = JdtUtil.getAnnotationParameterString(jsType, "prototype"); boolean isJsNative = jsPrototype != null; if (isJsNative) { @@ -55,7 +54,7 @@ public static void maybeSetJsInteropProperties(JDeclaredType type, Annotation... exportName = jsPrototype.substring(indexOf + 1); } boolean isJsType = jsType != null; - boolean isClassWideExport = exportName != null; + boolean isClassWideExport = JdtUtil.getAnnotation(annotations, JSEXPORT_CLASS) != null; boolean isJsFunction = JdtUtil.getAnnotation(annotations, JSFUNCTION_CLASS) != null; boolean canBeImplementedExternally = (type instanceof JInterfaceType && (isJsType || isJsFunction)) @@ -84,61 +83,60 @@ public static void maybeSetJsInteropPropertiesNew(JDeclaredType type, Annotation } public static void maybeSetJsInteropProperties(JMethod method, Annotation... annotations) { - setJsInteropProperties(method, annotations); - if (JdtUtil.getAnnotation(annotations, JSPROPERTY_CLASS) != null) { - setJsPropertyProperties(method, null); - } + boolean isPropertyAccessor = JdtUtil.getAnnotation(annotations, JSPROPERTY_CLASS) != null; + setJsInteropProperties(method, annotations, isPropertyAccessor); } public static void maybeSetJsInteropPropertiesNew(JMethod method, Annotation... annotations) { - AnnotationBinding annotation = getInteropAnnotation(annotations, "JsMethod"); if (getInteropAnnotation(annotations, "JsOverlay") != null) { method.setJsOverlay(); } + AnnotationBinding annotation = getInteropAnnotation(annotations, "JsMethod"); if (annotation == null) { annotation = getInteropAnnotation(annotations, "JsConstructor"); } - AnnotationBinding jsPropertyAnnotation = getInteropAnnotation(annotations, "JsProperty"); if (annotation == null) { - annotation = jsPropertyAnnotation; - } - setJsInteropPropertiesNew(method, annotations, annotation); - if (jsPropertyAnnotation != null) { - setJsPropertyProperties( - method, JdtUtil.getAnnotationParameterString(jsPropertyAnnotation, "name")); + annotation = getInteropAnnotation(annotations, "JsProperty"); } + + boolean isPropertyAccessor = getInteropAnnotation(annotations, "JsProperty") != null; + setJsInteropPropertiesNew(method, annotations, annotation, isPropertyAccessor); } public static void maybeSetJsInteropProperties(JField field, Annotation... annotations) { - setJsInteropProperties(field, annotations); + setJsInteropProperties(field, annotations, false); } public static void maybeSetJsInteropPropertiesNew(JField field, Annotation... annotations) { AnnotationBinding annotation = getInteropAnnotation(annotations, "JsProperty"); - setJsInteropPropertiesNew(field, annotations, annotation); + setJsInteropPropertiesNew(field, annotations, annotation, false); } - private static void setJsInteropProperties(JMember member, Annotation... annotations) { - String namespace = maybeGetJsNamespace(annotations); - String exportName = maybeGetJsExportName(annotations, computeName(member)); - member.setJsMemberInfo(namespace, exportName, exportName != null); + private static void setJsInteropProperties( + JMember member, Annotation[] annotations, boolean isPropertyAccessor) { + boolean hasExport = JdtUtil.getAnnotation(annotations, JSEXPORT_CLASS) != null; /* Apply class wide JsInterop annotations */ boolean ignore = JdtUtil.getAnnotation(annotations, JSNOEXPORT_CLASS) != null; - if (ignore || (!member.isPublic() && !isNativeConstructor(member)) || exportName != null) { + if (ignore || (!member.isPublic() && !isNativeConstructor(member)) || !hasExport) { return; } + String namespace = maybeGetJsNamespace(annotations); + String exportName = maybeGetJsExportName(annotations); + JsMemberType memberType = getJsMemberType(member, isPropertyAccessor); + member.setJsMemberInfo(memberType, namespace, exportName, hasExport); + JDeclaredType enclosingType = member.getEnclosingType(); if (enclosingType.isJsType() && member.needsDynamicDispatch()) { - member.setJsMemberInfo(namespace, computeName(member), true); + member.setJsMemberInfo(memberType, namespace, exportName, true); } if (enclosingType.isClassWideExport() && !member.needsDynamicDispatch()) { - member.setJsMemberInfo(namespace, computeName(member), true); + member.setJsMemberInfo(memberType, namespace, exportName, true); } } @@ -146,8 +144,8 @@ private static boolean isNativeConstructor(JMember member) { return member instanceof JConstructor && member.getEnclosingType().isJsNative(); } - private static void setJsInteropPropertiesNew( - JMember member, Annotation[] annotations, AnnotationBinding memberAnnotation) { + private static void setJsInteropPropertiesNew(JMember member, Annotation[] annotations, + AnnotationBinding memberAnnotation, boolean isAccessor) { if (getInteropAnnotation(annotations, "JsIgnore") != null) { return; } @@ -159,38 +157,43 @@ private static void setJsInteropPropertiesNew( String namespace = JdtUtil.getAnnotationParameterString(memberAnnotation, "namespace"); String name = JdtUtil.getAnnotationParameterString(memberAnnotation, "name"); - member.setJsMemberInfo(namespace, name == null ? computeName(member) : name, true); + JsMemberType memberType = getJsMemberType(member, isAccessor); + member.setJsMemberInfo(memberType, namespace, name, true); } - private static void setJsPropertyProperties(JMethod method, String name) { + private static JsMemberType getJsMemberType(JMember member, boolean isPropertyAccessor) { + if (member instanceof JField) { + return JsMemberType.PROPERTY; + } + if (member instanceof JConstructor) { + return JsMemberType.CONSTRUCTOR; + } + if (isPropertyAccessor) { + return getJsPropertyAccessorType((JMethod) member); + } + return JsMemberType.METHOD; + } + + private static JsMemberType getJsPropertyAccessorType(JMethod method) { if (method.getParams().size() == 1 && method.getType() == JPrimitiveType.VOID) { - method.setJsPropertyInfo(name, JsPropertyAccessorType.SETTER); + return JsMemberType.SETTER; } else if (method.getParams().isEmpty() && method.getType() != JPrimitiveType.VOID) { - method.setJsPropertyInfo(name, JsPropertyAccessorType.GETTER); - } else { - method.setJsPropertyInfo(name, JsPropertyAccessorType.UNDEFINED); + return JsMemberType.GETTER; } + return JsMemberType.UNDEFINED_ACCESSOR; } private static AnnotationBinding getInteropAnnotation(Annotation[] annotations, String name) { return JdtUtil.getAnnotation(annotations, "jsinterop.annotations." + name); } - private static String computeName(JMember member) { - return member instanceof JConstructor ? "" : member.getName(); - } - private static String maybeGetJsNamespace(Annotation[] annotations) { AnnotationBinding jsNamespace = JdtUtil.getAnnotation(annotations, JSNAMESPACE_CLASS); return JdtUtil.getAnnotationParameterString(jsNamespace, "value"); } - private static String maybeGetJsExportName(Annotation[] annotations, String calculatedName) { - AnnotationBinding jsExport = JdtUtil.getAnnotation(annotations, JSEXPORT_CLASS); - if (jsExport == null) { - return null; - } - String value = JdtUtil.getAnnotationParameterString(jsExport, "value"); - return Strings.isNullOrEmpty(value) ? calculatedName : value; + private static String maybeGetJsExportName(Annotation[] annotations) { + AnnotationBinding annotation = JdtUtil.getAnnotation(annotations, JSEXPORT_CLASS); + return JdtUtil.getAnnotationParameterString(annotation, "value"); } } diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java b/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java index a799f3387c2..75f6b6abd95 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/HasJsInfo.java @@ -15,14 +15,116 @@ */ package com.google.gwt.dev.jjs.ast; +import com.google.gwt.dev.javac.JsInteropUtil; + +import java.beans.Introspector; + /** * Abstracts JsInterop information for the AST nodes. */ public interface HasJsInfo extends HasJsName { + /** + * Indicates type of JsMember. + */ + enum JsMemberType { + /** + * Not a js member. + */ + NONE, + /** + * A JsConstructor. + */ + CONSTRUCTOR { + @Override + public String computeName(JMember member) { + return ""; + } + }, + /** + * A JsMethod. + */ + METHOD, + /** + * A JsProperty. + */ + PROPERTY, + /** + * A getter JsProperty accessor. Usually in the form of getX()/isX(). + */ + GETTER("get") { + @Override + public String computeName(JMember member) { + String methodName = member.getName(); + if (startsWithCamelCase(methodName, "get")) { + return Introspector.decapitalize(methodName.substring(3)); + } + if (startsWithCamelCase(methodName, "is")) { + return Introspector.decapitalize(methodName.substring(2)); + } + return JsInteropUtil.INVALID_JSNAME; + } + @Override + public boolean isPropertyAccessor() { + return true; + } + }, + /** + * A setter JsProperty accessor. Usually in the form of setX(x). + */ + SETTER("set") { + @Override + public String computeName(JMember member) { + String methodName = member.getName(); + if (startsWithCamelCase(methodName, "set")) { + return Introspector.decapitalize(methodName.substring(3)); + } + return JsInteropUtil.INVALID_JSNAME; + } + @Override + public boolean isPropertyAccessor() { + return true; + } + }, + /** + * A property accessor but doesn't match setter/getter patterns. + */ + UNDEFINED_ACCESSOR; + + private String accessorKey; + + private JsMemberType() { } + + private JsMemberType(String accessorKey) { + this.accessorKey = accessorKey; + } + + public String getPropertyAccessorKey() { + return accessorKey; + } - void setJsMemberInfo(String namespace, String name, boolean exported); + public boolean isPropertyAccessor() { + return getPropertyAccessorKey() != null; + } + + public String computeName(JMember member) { + return member.getName(); + } + + private static boolean startsWithCamelCase(String string, String prefix) { + return string.length() > prefix.length() && string.startsWith(prefix) + && Character.isUpperCase(string.charAt(prefix.length())); + } + } + + void setJsMemberInfo(JsMemberType type, String namespace, String name, boolean exported); + + JsMemberType getJsMemberType(); boolean isJsNative(); boolean isJsOverlay(); + + boolean canBeReferencedExternally(); + + boolean isJsInteropEntryPoint(); } diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java index cb8849605fd..535ff137363 100755 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JDeclaredType.java @@ -360,6 +360,10 @@ public final List getMethods() { return methods; } + public Iterable getMembers() { + return Iterables.concat(fields, methods); + } + @Override public boolean isJsType() { return isJsType; @@ -394,22 +398,16 @@ public boolean hasJsInteropEntryPoints() { return false; } + @Override public boolean canBeReferencedExternally() { if (isJsType()) { return true; } - for (JMethod method : getMethods()) { - if (method.canBeCalledExternally()) { + for (JMember member : getMembers()) { + if (member.canBeReferencedExternally()) { return true; } } - - for (JField field : getFields()) { - if (field.canBeReferencedExternally()) { - return true; - } - } - return false; } @@ -613,14 +611,17 @@ private JMethod getDefaultConstructor() { return null; } + @Override public String getJsName() { return Strings.isNullOrEmpty(jsName) ? getSimpleName() : jsName; } + @Override public String getJsNamespace() { return jsNamespace; } + @Override public String getQualifiedJsName() { return jsNamespace.isEmpty() ? getJsName() : jsNamespace + "." + getJsName(); } diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java index 26d48c40e0e..27edfb069d5 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java @@ -80,6 +80,7 @@ private Object readResolve() { public static final JField NULL_FIELD = new JField(SourceOrigin.UNKNOWN, "nullField", null, JReferenceType.NULL_TYPE, false, Disposition.FINAL); + private JsMemberType jsMembertype = JsMemberType.NONE; private String jsName; private String jsNamespace; private boolean exported; @@ -131,16 +132,25 @@ public JValueLiteral getLiteralInitializer() { } @Override - public void setJsMemberInfo(String namespace, String name, boolean exported) { - this.jsName = name; + public void setJsMemberInfo( + JsMemberType jsMembertype, String namespace, String name, boolean exported) { + this.jsMembertype = jsMembertype; + this.jsName = name != null ? name : jsMembertype.computeName(this); this.jsNamespace = namespace; this.exported = exported; } + @Override + public JsMemberType getJsMemberType() { + return jsMembertype; + } + + @Override public boolean isJsInteropEntryPoint() { - return exported && isStatic(); + return exported && isStatic() && !isJsNative(); } + @Override public boolean canBeReferencedExternally() { return exported; } @@ -161,10 +171,6 @@ public boolean isAbstract() { return false; } - public boolean isJsProperty() { - return jsName != null; - } - @Override public boolean isJsNative() { return enclosingType.isJsNative() && jsName != null; diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java index d73a3038379..c0ab0e3c509 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMember.java @@ -21,7 +21,7 @@ * Abstracts class members (i.e. fields and methods). */ public interface JMember extends HasEnclosingType, HasName, HasJsInfo, HasType, HasSourceInfo, - CanBeSetFinal, CanBeStatic, CanBeAbstract { + CanBeSetFinal, CanBeStatic, CanBeAbstract, CanHaveSuppressedWarnings { boolean isPublic(); diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java index 278b0fc7a95..98a574ff44d 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java @@ -26,7 +26,6 @@ import com.google.gwt.dev.util.collect.Lists; import com.google.gwt.thirdparty.guava.common.collect.Sets; -import java.beans.Introspector; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -40,76 +39,7 @@ /** * A Java method implementation. */ -public class JMethod extends JNode implements JMember, CanBeAbstract, CanHaveSuppressedWarnings { - - /** - * Indicates whether a method is a JsProperty accessor. - */ - public enum JsPropertyAccessorType { - /** - * Not a property accessor. - */ - NONE, - /** - * A getter property accessor. Usually in the form of getX()/isX(). - */ - GETTER("get") { - @Override - public String computeName(JMethod member) { - String methodName = member.getName(); - if (startsWithCamelCase(methodName, "get")) { - return Introspector.decapitalize(methodName.substring(3)); - } - if (startsWithCamelCase(methodName, "is")) { - return Introspector.decapitalize(methodName.substring(2)); - } - return JsInteropUtil.INVALID_JSNAME; - } - }, - /** - * A setter JsProperty accessor. Usually in the form of setX(x). - */ - SETTER("set") { - @Override - public String computeName(JMethod member) { - String methodName = member.getName(); - if (startsWithCamelCase(methodName, "set")) { - return Introspector.decapitalize(methodName.substring(3)); - } - return JsInteropUtil.INVALID_JSNAME; - } - }, - /** - * A property accessor but doesn't match setter/getter patterns. - */ - UNDEFINED; - - private String key; - - JsPropertyAccessorType() { - } - - JsPropertyAccessorType(String key) { - this.key = key; - } - - public String getKey() { - return key; - } - - public boolean isPropertyAccessor() { - return key != null; - } - - public String computeName(JMethod method) { - return method.getName(); - } - - private static boolean startsWithCamelCase(String string, String prefix) { - return string.length() > prefix.length() && string.startsWith(prefix) - && Character.isUpperCase(string.charAt(prefix.length())); - } - } +public class JMethod extends JNode implements JMember, CanBeAbstract { public static final Comparator BY_SIGNATURE_COMPARATOR = new Comparator() { @Override @@ -121,7 +51,7 @@ public int compare(JMethod m1, JMethod m2) { private String jsName; private boolean exported; private String jsNamespace; - private JsPropertyAccessorType jsPropertyType = JsPropertyAccessorType.NONE; + private JsMemberType jsMemberType = JsMemberType.NONE; private Specialization specialization; private InliningMode inliningMode = InliningMode.NORMAL; private boolean preventDevirtualization = false; @@ -132,17 +62,20 @@ public int compare(JMethod m1, JMethod m2) { private boolean isJsOverlay = false; @Override - public void setJsMemberInfo(String namespace, String name, boolean exported) { - this.jsName = name; + public void setJsMemberInfo(JsMemberType type, String namespace, String name, boolean exported) { + this.jsMemberType = type; + this.jsName = name != null ? name : type.computeName(this); this.jsNamespace = namespace; this.exported = exported; } + @Override public boolean isJsInteropEntryPoint() { return exported && !needsDynamicDispatch() && !isJsNative(); } - public boolean canBeCalledExternally() { + @Override + public boolean canBeReferencedExternally() { if (exported || isJsFunctionMethod()) { return true; } @@ -209,58 +142,38 @@ public boolean isJsConstructor() { } /** - * Returns {@code true} if this method is the first JsMethod in the method hierarchy that exposes - * an existing non-JsMethod inside a class. + * Returns {@code true} if this method is the first JsMember in the method hierarchy that exposes + * an existing non-JsMember inside a class. */ - public boolean exposesNonJsMethod() { - if (isInterfaceMethod() || !isOrOverridesJsMethod()) { + public boolean exposesNonJsMember() { + if (isInterfaceMethod() || getJsMemberType() == JsMemberType.NONE) { return false; } - boolean hasNonJsMethodParent = false; + boolean hasNonJsMemberParent = false; for (JMethod overriddenMethod : overriddenMethods) { - if (!overriddenMethod.isOrOverridesJsMethod()) { - hasNonJsMethodParent = true; + if (overriddenMethod.getJsMemberType() == JsMemberType.NONE) { + hasNonJsMemberParent = true; } - if (overriddenMethod.exposesNonJsMethod()) { + if (overriddenMethod.exposesNonJsMember()) { return false; // some other method already exposed this method. } } - return hasNonJsMethodParent; - } - - public boolean isOrOverridesJsMethod() { - if (jsName != null) { - return true; - } - for (JMethod overriddenMethod : getOverriddenMethods()) { - if (overriddenMethod.jsName != null) { - return true; - } - } - return false; - } - - public void setJsPropertyInfo(String jsName, JsPropertyAccessorType jsPropertyType) { - this.jsName = jsName != null ? jsName : jsPropertyType.computeName(this); - this.jsPropertyType = jsPropertyType; + return hasNonJsMemberParent; } - public JsPropertyAccessorType getJsPropertyAccessorType() { - if (isJsPropertyAccessor()) { - return jsPropertyType; + @Override + public JsMemberType getJsMemberType() { + if (jsMemberType != JsMemberType.NONE) { + return jsMemberType; } for (JMethod overriddenMethod : getOverriddenMethods()) { - if (overriddenMethod.isJsPropertyAccessor()) { - return overriddenMethod.jsPropertyType; + if (overriddenMethod.jsMemberType != JsMemberType.NONE) { + return overriddenMethod.jsMemberType; } } - return JsPropertyAccessorType.NONE; - } - - private boolean isJsPropertyAccessor() { - return jsPropertyType != JsPropertyAccessorType.NONE; + return JsMemberType.NONE; } private boolean isJsFunctionMethod() { @@ -284,6 +197,7 @@ public boolean isJsNative() { return (isAbstract || body == null) && jsName != null; } + @Override public boolean isJsOverlay() { return isJsOverlay || (getEnclosingType() != null && getEnclosingType().isJsoType()); } @@ -690,6 +604,7 @@ public boolean isJsniMethod() { } } + @Override public boolean isPrivate() { return access == AccessModifier.PRIVATE.ordinal(); } @@ -704,6 +619,7 @@ public boolean isStatic() { return isStatic; } + @Override public boolean isSynthetic() { return isSynthetic; } diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java index 8b2710a0c81..9d9faa49e11 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowAnalyzer.java @@ -616,7 +616,7 @@ private void rescue(JMethod method) { // Returning from this method passes a value from JavaScript into Java. maybeRescueJavaScriptObjectPassingIntoJava(method.getType()); } - if (method.canBeCalledExternally() || method.canBeImplementedExternally()) { + if (method.canBeReferencedExternally() || method.canBeImplementedExternally()) { for (JParameter param : method.getParams()) { // Parameters in JsExport, JsType, JsFunction methods should not be pruned in order to // keep the API intact. @@ -683,7 +683,7 @@ private void rescue(JReferenceType type, boolean isInstantiated) { JDeclaredType declaredType = (JDeclaredType) type; for (JMethod method : declaredType.getMethods()) { - if (method.canBeCalledExternally()) { + if (method.canBeReferencedExternally()) { rescue(method); } } diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowRecorder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowRecorder.java index ee30b3546cf..d13ed829394 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowRecorder.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ControlFlowRecorder.java @@ -137,7 +137,7 @@ public boolean visit(JMethod x, Context ctx) { overriddenMethodName); } - if (x.canBeCalledExternally()) { + if (x.canBeReferencedExternally()) { stringAnalyzableTypeEnvironment.recordExportedMethodInType(currentMethodName, typeName); } diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java index 07552c3c3dc..9cbda78a09b 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java @@ -30,6 +30,7 @@ import com.google.gwt.dev.jjs.SourceOrigin; import com.google.gwt.dev.jjs.ast.Context; import com.google.gwt.dev.jjs.ast.HasEnclosingType; +import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType; import com.google.gwt.dev.jjs.ast.HasName; import com.google.gwt.dev.jjs.ast.JAbstractMethodBody; import com.google.gwt.dev.jjs.ast.JArrayLength; @@ -64,7 +65,6 @@ import com.google.gwt.dev.jjs.ast.JLocalRef; import com.google.gwt.dev.jjs.ast.JMember; 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.JMethodCall; import com.google.gwt.dev.jjs.ast.JNameOf; @@ -241,7 +241,7 @@ public void endVisit(JField x, Context ctx) { jsName = topScope.declareName(mangleName(x), x.getName()); } else { jsName = - x.isJsProperty() + x.getJsMemberType() != JsMemberType.NONE ? scopeStack.peek().declareUnobfuscatableName(x.getJsName()) : scopeStack.peek().declareName(mangleName(x), x.getName()); } @@ -366,9 +366,8 @@ public boolean visit(JMethod x, Context ctx) { } else if (x.isPackagePrivate()) { polyName = interfaceScope.declareName(mangleNameForPackagePrivatePoly(x), name); } else { - boolean isJsMethod = x.isOrOverridesJsMethod(); polyName = - isJsMethod + x.getJsMemberType() != JsMemberType.NONE ? interfaceScope.declareUnobfuscatableName(x.getJsName()) : interfaceScope.declareName(mangleNameForPoly(x), name); } @@ -886,7 +885,7 @@ private JsExpression dispatchToStatic(JsExpression unnecessaryQualifier, JMethod List args, SourceInfo sourceInfo) { JsNameRef methodName = createStaticReference(method, sourceInfo); JsExpression result = JsUtils.createInvocationOrPropertyAccess( - sourceInfo, method.getJsPropertyAccessorType(), methodName, args); + sourceInfo, method.getJsMemberType(), methodName, args); return JsUtils.createCommaExpression(unnecessaryQualifier, result); } @@ -945,10 +944,8 @@ private JsExpression dispatchToJsFunction( private JsExpression dispatchToInstanceMethod( JsExpression instance, JMethod method, List args, SourceInfo sourceInfo) { JsNameRef reference = polymorphicNames.get(method).makeQualifiedRef(sourceInfo, instance); - - JsPropertyAccessorType propertyAccessorType = method.getJsPropertyAccessorType(); - return JsUtils - .createInvocationOrPropertyAccess(sourceInfo, propertyAccessorType, reference, args); + return JsUtils.createInvocationOrPropertyAccess( + sourceInfo, method.getJsMemberType(), reference, args); } @Override @@ -1456,24 +1453,18 @@ private void generateExports() { exportedMembersByExportName.put(type.getQualifiedJsName(), type); } - for (JMethod method : type.getMethods()) { - if (method.isJsInteropEntryPoint()) { - exportedMembersByExportName.put(method.getQualifiedJsName(), method); - } - } - - for (JField field : type.getFields()) { - if (field.isJsInteropEntryPoint()) { - if (!field.isFinal()) { - // TODO(rluble): move waring to JsInteropRestrictionChecker. + for (JMember member : type.getMembers()) { + if (member.isJsInteropEntryPoint()) { + if (member.getJsMemberType() == JsMemberType.PROPERTY && !member.isFinal()) { + // TODO(goktug): Remove the warning when we export via Object.defineProperty logger.log( TreeLogger.Type.WARN, "Exporting effectively non-final field " - + field.getQualifiedName() + + member.getQualifiedName() + ". Due to the way exporting works, the value of the" + " exported field will not be reflected across Java/JavaScript border."); } - exportedMembersByExportName.put(field.getQualifiedJsName(), field); + exportedMembersByExportName.put(member.getQualifiedJsName(), member); } } } @@ -2221,7 +2212,7 @@ private void maybeGenerateToStringAlias(JDeclaredType type) { } private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs) { - generatePrototypeAssignment(method, name, rhs, method.getJsPropertyAccessorType()); + generatePrototypeAssignment(method, name, rhs, method.getJsMemberType()); } /** @@ -2229,11 +2220,11 @@ private void generatePrototypeAssignment(JMethod method, JsName name, JsExpressi * created for {@code method}. */ private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs, - JsPropertyAccessorType accessorType) { + JsMemberType memberType) { SourceInfo sourceInfo = method.getSourceInfo(); JsNameRef prototypeQualifierOf = getPrototypeQualifierOf(method); JsNameRef lhs = name.makeQualifiedRef(sourceInfo, prototypeQualifierOf); - switch (accessorType) { + switch (memberType) { case GETTER: case SETTER: emitPropertyImplementation(method, prototypeQualifierOf, name.makeRef(sourceInfo), rhs); @@ -2260,7 +2251,7 @@ private void emitPropertyImplementation(JMethod method, JsNameRef prototype, JsN // {name: {get: function() { ..... }} or {set : function (v) {....}}} .add(name, JsObjectLiteral.builder(sourceInfo) // {get: function() { ..... }} or {set : function (v) {....}} - .add(method.getJsPropertyAccessorType().getKey(), methodDefinitionStatement) + .add(method.getJsMemberType().getPropertyAccessorKey(), methodDefinitionStatement) .build()) .build(); @@ -2282,7 +2273,7 @@ private void generatePrototypeDefinitionAlias(JMethod method, JsName alias) { JsName polyName = polymorphicNames.get(method); JsExpression bridge = JsUtils.createBridge(method, polyName, topScope); // Aliases are never property accessors. - generatePrototypeAssignment(method, alias, bridge, JsPropertyAccessorType.NONE); + generatePrototypeAssignment(method, alias, bridge, JsMemberType.NONE); } private JsExprStmt outputDisplayName(JsNameRef function, JMethod method) { @@ -2332,7 +2323,7 @@ private void generatePrototypeDefinition(JMethod method, JsExpression functionDe generatePrototypeAssignment(method, polymorphicNames.get(method), functionDefinition); } - if (method.exposesNonJsMethod()) { + if (method.exposesNonJsMember()) { JsName internalMangledName = interfaceScope.declareName(mangleNameForPoly(method), method.getName()); generatePrototypeDefinitionAlias(method, internalMangledName); diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java index 024cf91211b..73fbfea3004 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JjsUtils.java @@ -386,7 +386,7 @@ public boolean apply(JMethod method) { }); // A synthetic accidental override is unnecessary iff it retains the same property // name (polyname) as the the concrete method it overrides. - return overridesConcreteMethod && !method.exposesNonJsMethod(); + return overridesConcreteMethod && !method.exposesNonJsMember(); } /** diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java index c0f8ab6aa84..f1dbe2b5282 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JsInteropRestrictionChecker.java @@ -21,7 +21,9 @@ import com.google.gwt.dev.jjs.HasSourceInfo; import com.google.gwt.dev.jjs.ast.CanHaveSuppressedWarnings; import com.google.gwt.dev.jjs.ast.Context; +import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType; import com.google.gwt.dev.jjs.ast.HasJsName; +import com.google.gwt.dev.jjs.ast.HasType; import com.google.gwt.dev.jjs.ast.JClassType; import com.google.gwt.dev.jjs.ast.JConstructor; import com.google.gwt.dev.jjs.ast.JDeclarationStatement; @@ -34,7 +36,6 @@ import com.google.gwt.dev.jjs.ast.JInterfaceType; import com.google.gwt.dev.jjs.ast.JMember; 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.JMethodCall; import com.google.gwt.dev.jjs.ast.JParameter; @@ -226,50 +227,32 @@ private boolean isDelegatingToConstructor(JConstructor ctor, JConstructor target return call.getTarget().equals(targetCtor); } - private void checkField(Map localNames, JField field) { - if (field.getEnclosingType().isJsNative()) { - checkMemberOfNativeJsType(field); + private void checkMember(Map localNames, JMember member) { + if (member.getEnclosingType().isJsNative()) { + checkMemberOfNativeJsType(member); } - checkUnusableByJs(field); - - if (!field.isJsProperty()) { + if (member.isJsOverlay()) { + checkJsOverlay((JMethod) member); return; } - checkMemberQualifiedJsName(field); - - if (field.needsDynamicDispatch()) { - checkLocalName(localNames, field); - } else if (!field.isJsNative()) { - checkGlobalName(field); - } - } - - private void checkMethod(Map localNames, JMethod method) { - if (method.getEnclosingType().isJsNative()) { - checkMemberOfNativeJsType(method); + if (member.canBeReferencedExternally()) { + checkUnusableByJs(member); } - if (method.isJsOverlay()) { - checkJsOverlay(method); + if (member.getJsMemberType() == JsMemberType.NONE) { return; } - checkUnusableByJs(method); + checkMemberQualifiedJsName(member); - if (!method.isOrOverridesJsMethod()) { - return; + if (isCheckedLocalName(member)) { + checkLocalName(localNames, member); } - checkMemberQualifiedJsName(method); - - if (method.needsDynamicDispatch()) { - if (!isSyntheticBridgeMethod(method)) { - checkLocalName(localNames, method); - } - } else if (!method.isJsNative()) { - checkGlobalName(method); + if (isCheckedGlobalName(member)) { + checkGlobalName(member); } } @@ -286,8 +269,7 @@ private void checkGlobalName(JMember member) { private void checkLocalName(Map localNames, JMember member) { if (member.getJsName().equals(JsInteropUtil.INVALID_JSNAME)) { - if (member instanceof JMethod - && ((JMethod) member).getJsPropertyAccessorType().isPropertyAccessor()) { + if (member.getJsMemberType().isPropertyAccessor()) { logError( member, "JsProperty %s should either follow Java Bean naming conventions or " @@ -319,27 +301,23 @@ private void checkLocalName(Map localNames, JMember member) { getMemberDescription(member), getMemberDescription(oldMember.member), member.getJsName()); } - private void checkJsPropertyAccessor(JMember x, JsMember newMember) { - if (!(x instanceof JMethod)) { - return; - } - JMethod method = (JMethod) x; - - if (method.getJsPropertyAccessorType() == JsPropertyAccessorType.UNDEFINED) { - logError(method, "JsProperty %s should have a correct setter or getter signature.", - getMemberDescription(method)); + private void checkJsPropertyAccessor(JMember member, JsMember newMember) { + if (member.getJsMemberType() == JsMemberType.UNDEFINED_ACCESSOR) { + logError(member, "JsProperty %s should have a correct setter or getter signature.", + getMemberDescription(member)); } - if (method.getJsPropertyAccessorType() == JsPropertyAccessorType.GETTER) { - if (method.getType() != JPrimitiveType.BOOLEAN && method.getName().startsWith("is")) { - logError(method, "JsProperty %s cannot have a non-boolean return.", - getMemberDescription(method)); + if (member.getJsMemberType() == JsMemberType.GETTER) { + if (member.getType() != JPrimitiveType.BOOLEAN && member.getName().startsWith("is")) { + logError(member, "JsProperty %s cannot have a non-boolean return.", + getMemberDescription(member)); } } if (newMember.setter != null && newMember.getter != null) { - if (newMember.getter.getType() != newMember.setter.getParams().get(0).getType()) { - logError(method, "JsProperty setter %s and getter %s cannot have inconsistent types.", + List setterParams = ((JMethod) newMember.setter).getParams(); + if (newMember.getter.getType() != setterParams.get(0).getType()) { + logError(member, "JsProperty setter %s and getter %s cannot have inconsistent types.", getMemberDescription(newMember.setter), getMemberDescription(newMember.getter)); } } @@ -447,7 +425,7 @@ public boolean visit(JMethod x, Context ctx) { @Override public void endVisit(JMethodCall x, Context ctx) { JMethod target = x.getTarget(); - if (x.isStaticDispatchOnly() && target.getJsPropertyAccessorType().isPropertyAccessor()) { + if (x.isStaticDispatchOnly() && target.getJsMemberType().isPropertyAccessor()) { logError(x, "Cannot call property accessor %s via super.", getMemberDescription(target)); } @@ -603,62 +581,45 @@ private void checkType(JDeclaredType type) { } Map localNames = collectNames(type.getSuperClass()); - - for (JField field : type.getFields()) { - checkField(localNames, field); - } - for (JMethod method : type.getMethods()) { - checkMethod(localNames, method); + for (JMember member : type.getMembers()) { + checkMember(localNames, member); } } - private void checkUnusableByJs(JMethod method) { - if (!method.canBeCalledExternally() || isUnusableByJsSuppressed(method.getEnclosingType()) - || isUnusableByJsSuppressed(method)) { - return; - } - // check parameters. - for (JParameter parameter : method.getParams()) { - if (!parameter.getType().canBeReferencedExternally() - && !isUnusableByJsSuppressed(parameter)) { - logWarning( - parameter, - "[unusable-by-js] Type of parameter '%s' in method %s is not usable by but exposed to" - + " JavaScript.", - parameter.getName(), getMemberDescription(method)); + private void checkUnusableByJs(JMember member) { + logIfUnusableByJs(member, member instanceof JField ? "Type of" : "Return type of", member); + + if (member instanceof JMethod) { + for (JParameter parameter : ((JMethod) member).getParams()) { + String prefix = String.format("Type of parameter '%s' in", parameter.getName()); + logIfUnusableByJs(parameter, prefix, member); } } - // check return type. - if (!method.getType().canBeReferencedExternally()) { - logWarning( - method, "[unusable-by-js] Return type of %s is not usable by but exposed to JavaScript.", - getMemberDescription(method)); - } } - private void checkUnusableByJs(JField field) { - if (!field.canBeReferencedExternally() || isUnusableByJsSuppressed(field.getEnclosingType()) - || isUnusableByJsSuppressed(field)) { + private void logIfUnusableByJs( + T hasType, String prefix, JMember x) { + if (hasType.getType().canBeReferencedExternally()) { return; } - if (!field.getType().canBeReferencedExternally()) { - logWarning( - field, "[unusable-by-js] Type of field '%s' in type '%s' is not usable by but exposed to " - + "JavaScript.", - field.getName(), JjsUtils.getReadableDescription(field.getEnclosingType())); + if (isUnusableByJsSuppressed(x.getEnclosingType()) || isUnusableByJsSuppressed(x) + || isUnusableByJsSuppressed(hasType)) { + return; } + logWarning(x, "[unusable-by-js] %s %s is not usable by but exposed to JavaScript.", prefix, + getMemberDescription(x)); } private static class JsMember { private JMember member; - private JMethod setter; - private JMethod getter; + private JMember setter; + private JMember getter; public JsMember(JMember member) { this.member = member; } - public JsMember(JMethod member, JMethod setter, JMethod getter) { + public JsMember(JMember member, JMember setter, JMember getter) { this.member = member; this.setter = setter; this.getter = getter; @@ -679,24 +640,23 @@ private LinkedHashMap collectNames(JDeclaredType type) { } LinkedHashMap memberByLocalMemberNames = collectNames(type.getSuperClass()); - - for (JField field : type.getFields()) { - if (!field.isJsProperty() || !field.needsDynamicDispatch()) { - continue; + for (JMember member : type.getMembers()) { + if (isCheckedLocalName(member)) { + updateJsMembers(memberByLocalMemberNames, member); } - updateJsMembers(memberByLocalMemberNames, field); - } - for (JMethod method : type.getMethods()) { - if (!method.isOrOverridesJsMethod() || !method.needsDynamicDispatch() - || isSyntheticBridgeMethod(method)) { - continue; - } - updateJsMembers(memberByLocalMemberNames, method); } return memberByLocalMemberNames; } - private boolean isSyntheticBridgeMethod(JMethod method) { + private boolean isCheckedLocalName(JMember method) { + return method.needsDynamicDispatch() && method.getJsMemberType() != JsMemberType.NONE + && !isSyntheticBridgeMethod(method); + } + + private boolean isSyntheticBridgeMethod(JMember member) { + if (!(member instanceof JMethod)) { + return false; + } // A name slot taken up by a synthetic method, such as a bridge method for a generic method, // is not the fault of the user and so should not be reported as an error. JS generation // should take responsibility for ensuring that only the correct method version (in this @@ -704,7 +664,11 @@ private boolean isSyntheticBridgeMethod(JMethod method) { // (such as an accidental override forwarding method that occurs when a JsType interface // starts exposing a method in class B that is only ever implemented in its parent class A) // though should be checked since they are exported and do take up an name slot. - return method.isSynthetic() && !method.isForwarding(); + return member.isSynthetic() && !((JMethod) member).isForwarding(); + } + + private boolean isCheckedGlobalName(JMember member) { + return !member.needsDynamicDispatch() && !member.isJsNative(); } private void updateJsMembers(Map memberByLocalMemberNames, JMember member) { @@ -714,45 +678,41 @@ private void updateJsMembers(Map memberByLocalMemberNames, JMe } private JsMember createOrUpdateJsMember(JsMember jsMember, JMember member) { - if (member instanceof JField) { - return new JsMember(member); - } - - JMethod method = (JMethod) member; - switch (method.getJsPropertyAccessorType()) { + switch (member.getJsMemberType()) { case GETTER: if (jsMember != null && jsMember.isPropertyAccessor()) { - if (jsMember.getter == null || overrides(method, jsMember.getter)) { - jsMember.getter = method; - jsMember.member = method; + if (jsMember.getter == null || overrides(member, jsMember.getter)) { + jsMember.getter = member; + jsMember.member = member; return jsMember; } } - return new JsMember(method, jsMember == null ? null : jsMember.setter, method); + return new JsMember(member, jsMember == null ? null : jsMember.setter, member); case SETTER: if (jsMember != null && jsMember.isPropertyAccessor()) { - if (jsMember.setter == null || overrides(method, jsMember.setter)) { - jsMember.setter = method; - jsMember.member = method; + if (jsMember.setter == null || overrides(member, jsMember.setter)) { + jsMember.setter = member; + jsMember.member = member; return jsMember; } } - return new JsMember(method, method, jsMember == null ? null : jsMember.getter); + return new JsMember(member, member, jsMember == null ? null : jsMember.getter); default: if (jsMember != null) { - if (overrides(method, jsMember.member)) { - jsMember.member = method; + if (overrides(member, jsMember.member)) { + jsMember.member = member; return jsMember; } } - return new JsMember(method); + return new JsMember(member); } } - private boolean overrides(JMethod method, JMember potentiallyOverriddenMember) { - if (potentiallyOverriddenMember instanceof JField) { + private boolean overrides(JMember member, JMember potentiallyOverriddenMember) { + if (member instanceof JField || potentiallyOverriddenMember instanceof JField) { return false; } + JMethod method = (JMethod) member; if (method.getOverriddenMethods().contains(potentiallyOverriddenMember)) { return true; } diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/SameParameterValueOptimizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/SameParameterValueOptimizer.java index 275dbce33e3..7c8dba69676 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/SameParameterValueOptimizer.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/SameParameterValueOptimizer.java @@ -127,7 +127,7 @@ public boolean visit(JMethod x, Context ctx) { } private boolean isNotOptimizable(JMethod x) { - return x.needsDynamicDispatch() || x.canBeCalledExternally(); + return x.needsDynamicDispatch() || x.canBeReferencedExternally(); } private boolean equalLiterals(JValueLiteral l1, JValueLiteral l2) { diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java index 76751e1428c..f42ba3bee47 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java @@ -564,7 +564,7 @@ public void endVisit(JMethodCall x, Context ctx) { public void endVisit(JParameter x, Context ctx) { JMethod currentMethod = getCurrentMethod(); if (program.codeGenTypes.contains(currentMethod.getEnclosingType()) - || currentMethod.canBeCalledExternally()) { + || currentMethod.canBeReferencedExternally()) { // We cannot tighten this parameter as we don't know all callers. return; } diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java index 3433c78e702..19f51519019 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/UnifyAst.java @@ -1329,7 +1329,7 @@ private void instantiate(JDeclaredType type) { // Flow into any reachable virtual methods. for (JMethod method : type.getMethods()) { - if (method.canBeCalledExternally()) { + if (method.canBeReferencedExternally()) { flowInto(method); continue; } diff --git a/dev/core/src/com/google/gwt/dev/js/JsUtils.java b/dev/core/src/com/google/gwt/dev/js/JsUtils.java index 729c74ec9d3..bc296c7c671 100644 --- a/dev/core/src/com/google/gwt/dev/js/JsUtils.java +++ b/dev/core/src/com/google/gwt/dev/js/JsUtils.java @@ -16,8 +16,8 @@ package com.google.gwt.dev.js; import com.google.gwt.dev.jjs.SourceInfo; +import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType; 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.JPrimitiveType; import com.google.gwt.dev.jjs.ast.JProgram; @@ -108,7 +108,7 @@ public static JsFunction createBridge(JMethod method, JsName polyName, JsScope s } JsExpression invocation = - createInvocationOrPropertyAccess(sourceInfo, method.getJsPropertyAccessorType(), ref, args); + createInvocationOrPropertyAccess(sourceInfo, method.getJsMemberType(), ref, args); JsBlock block = new JsBlock(sourceInfo); if (method.getType() == JPrimitiveType.VOID) { @@ -162,8 +162,8 @@ public static JsNameRef createQualifiedNameRef(SourceInfo info, JsName... names } public static JsExpression createInvocationOrPropertyAccess(SourceInfo sourceInfo, - JsPropertyAccessorType propertyAccessorType, JsNameRef reference, List args) { - switch (propertyAccessorType) { + JsMemberType memberType, JsNameRef reference, List args) { + switch (memberType) { case SETTER: assert args.size() == 1; return createAssignment(reference, args.get(0)); diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java index 9aaf79f41f9..656fbd74e66 100644 --- a/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java +++ b/dev/core/test/com/google/gwt/dev/jjs/impl/JsInteropRestrictionCheckerTest.java @@ -1850,7 +1850,7 @@ public void testUnusuableByJsWarns() throws Exception { "}", "@JsFunction public static interface FI { void f(A a); }", // JsFunction method is checked. "@JsType public static class Buggy {", - " public A field;", // exported field + " public A f;", // exported field " public A f1(A a) { return null; }", // regular class fails. " public A[] f2(A[] a) { return null; }", // array of regular class fails. " public long f3(long a) { return 1l; }", // long fails. @@ -1861,39 +1861,38 @@ public void testUnusuableByJsWarns() throws Exception { "}"); assertBuggySucceeds( + "Line 12: [unusable-by-js] Type of parameter 'a' in " + + "'void EntryPoint.C.fc1(EntryPoint.A)' is not usable by but exposed to JavaScript.", + "Line 16: [unusable-by-js] Type of 'EntryPoint.A EntryPoint.D.a' is not usable by but " + + "exposed to JavaScript.", + "Line 18: [unusable-by-js] Type of parameter 'a' in " + + "'void EntryPoint.FI.f(EntryPoint.A)' is not usable by but exposed to JavaScript.", + "Line 20: [unusable-by-js] Type of 'EntryPoint.A EntryPoint.Buggy.f' is not usable by but " + + "exposed to JavaScript.", "Line 21: [unusable-by-js] Return type of 'EntryPoint.A EntryPoint.Buggy.f1(EntryPoint.A)' " + "is not usable by but exposed to JavaScript.", + "Line 21: [unusable-by-js] Type of parameter 'a' in " + + "'EntryPoint.A EntryPoint.Buggy.f1(EntryPoint.A)' is not usable by but " + + "exposed to JavaScript.", "Line 22: [unusable-by-js] Return type of " + "'EntryPoint.A[] EntryPoint.Buggy.f2(EntryPoint.A[])' is not usable by but " + "exposed to JavaScript.", + "Line 22: [unusable-by-js] Type of parameter 'a' in " + + "'EntryPoint.A[] EntryPoint.Buggy.f2(EntryPoint.A[])' is not usable by but " + + "exposed to JavaScript.", "Line 23: [unusable-by-js] Return type of 'long EntryPoint.Buggy.f3(long)' is not " + "usable by but exposed to JavaScript.", + "Line 23: [unusable-by-js] Type of parameter 'a' in " + + "'long EntryPoint.Buggy.f3(long)' is not usable by but exposed to JavaScript.", "Line 24: [unusable-by-js] Return type of 'EntryPoint.B EntryPoint.Buggy.f4(EntryPoint.B)' " + "is not usable by but exposed to JavaScript.", - "Line 20: [unusable-by-js] Type of field 'field' in type 'EntryPoint.Buggy' " - + "is not usable by but exposed to JavaScript.", - "Line 21: [unusable-by-js] Type of parameter 'a' in method " - + "'EntryPoint.A EntryPoint.Buggy.f1(EntryPoint.A)' is not usable by but " - + "exposed to JavaScript.", - "Line 22: [unusable-by-js] Type of parameter 'a' in method " - + "'EntryPoint.A[] EntryPoint.Buggy.f2(EntryPoint.A[])' is not usable by but " - + "exposed to JavaScript.", - "Line 23: [unusable-by-js] Type of parameter 'a' in method " - + "'long EntryPoint.Buggy.f3(long)' is not usable by but exposed to JavaScript.", - "Line 24: [unusable-by-js] Type of parameter 'a' in method " + "Line 24: [unusable-by-js] Type of parameter 'a' in " + "'EntryPoint.B EntryPoint.Buggy.f4(EntryPoint.B)' is not usable by but " + "exposed to JavaScript.", - "Line 25: [unusable-by-js] Type of parameter 'a' in method " + "Line 25: [unusable-by-js] Type of parameter 'a' in " + "'void EntryPoint.Buggy.f5(Object[][])' is not usable by but exposed to JavaScript.", - "Line 26: [unusable-by-js] Type of parameter 'a' in method " - + "'void EntryPoint.Buggy.f6(Object[])' is not usable by but exposed to JavaScript.", - "Line 18: [unusable-by-js] Type of parameter 'a' in method " - + "'void EntryPoint.FI.f(EntryPoint.A)' is not usable by but exposed to JavaScript.", - "Line 12: [unusable-by-js] Type of parameter 'a' in method " - // JsMethod in non-jstype class. - + "'void EntryPoint.C.fc1(EntryPoint.A)' is not usable by but exposed to JavaScript.", - "Line 16: [unusable-by-js] Type of field 'a' in type " // JsProperty in non-jstype class. - + "'EntryPoint.D' is not usable by but exposed to JavaScript."); + "Line 26: [unusable-by-js] Type of parameter 'a' in " + + "'void EntryPoint.Buggy.f6(Object[])' is not usable by but exposed to JavaScript."); } public void testUnusableByJsAccidentalOverrideSuppressionWarns() @@ -1911,7 +1910,7 @@ public void testUnusableByJsAccidentalOverrideSuppressionWarns() "public static class Buggy extends Parent implements Foo {}"); assertBuggySucceeds( - "Line 10: [unusable-by-js] Type of parameter 'x' in method " + "Line 10: [unusable-by-js] Type of parameter 'x' in " + "'void EntryPoint.Parent.doIt(Class)' (exposed by 'EntryPoint.Buggy') is not usable " + "by but exposed to JavaScript."); }