Fixed bug where standard methods names may become obfuscated.

This commit is contained in:
Pavel Talanov
2012-01-17 14:57:14 +04:00
parent a6e8ceb3e4
commit 85d645e8fb
9 changed files with 140 additions and 64 deletions
@@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import java.util.Set;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getNameForNamespace; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getNameForNamespace;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getOwnDeclarations; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getOwnDeclarations;
@@ -41,6 +43,7 @@ public final class DeclarationVisitor extends DeclarationDescriptorVisitor<Void,
private JsName declareName(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context, private JsName declareName(@NotNull DeclarationDescriptor descriptor, @NotNull DeclarationContext context,
@NotNull String name) { @NotNull String name) {
JsName jsName = context.getScope().declareVariable(descriptor, name, shouldObfuscate); JsName jsName = context.getScope().declareVariable(descriptor, name, shouldObfuscate);
jsName.setObfuscatable(false);
declarations.putName(descriptor, jsName); declarations.putName(descriptor, jsName);
declarations.putQualifier(descriptor, context.getQualifier()); declarations.putQualifier(descriptor, context.getQualifier());
return jsName; return jsName;
@@ -85,11 +88,27 @@ public final class DeclarationVisitor extends DeclarationDescriptorVisitor<Void,
@Override @Override
public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull DeclarationContext context) { public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull DeclarationContext context) {
boolean overridesDeclaredDescriptor = declareAsOverridden(descriptor, context);
if (overridesDeclaredDescriptor) {
return null;
}
declareName(descriptor, context); declareName(descriptor, context);
declareScope(descriptor, context, "function " + descriptor.getName()); declareScope(descriptor, context, "function " + descriptor.getName());
return null; return null;
} }
private boolean declareAsOverridden(@NotNull FunctionDescriptor descriptor, @NotNull DeclarationContext context) {
Set<? extends FunctionDescriptor> overriddenDescriptors = descriptor.getOverriddenDescriptors();
for (FunctionDescriptor overriddenDescriptor : overriddenDescriptors) {
if (declarations.hasDeclaredName(overriddenDescriptor)) {
declarations.putName(descriptor, declarations.getName(overriddenDescriptor));
declareScope(descriptor, context, "function " + descriptor.getName());
return true;
}
}
return false;
}
@Override @Override
public Void visitPropertyDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull DeclarationContext context) { public Void visitPropertyDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull DeclarationContext context) {
String propertyName = descriptor.getName(); String propertyName = descriptor.getName();
@@ -33,9 +33,16 @@ public final class StandardClasses {
declareJavaArrayList(standardClasses); declareJavaArrayList(standardClasses);
declareJavaSystem(standardClasses); declareJavaSystem(standardClasses);
declareJavaInteger(standardClasses); declareJavaInteger(standardClasses);
declareJavaUtilIterator(standardClasses);
return standardClasses; return standardClasses;
} }
private static void declareJavaUtilIterator(@NotNull StandardClasses standardClasses) {
String iteratorFQName = "<java_root>.java.util.Iterator";
standardClasses.declareStandardTopLevelObject(iteratorFQName, "Iterator");
declareMethods(standardClasses, iteratorFQName, "next", "hasNext");
}
private static void declareString(@NotNull StandardClasses standardClasses) { private static void declareString(@NotNull StandardClasses standardClasses) {
String stringFQName = "jet.String"; String stringFQName = "jet.String";
standardClasses.declareStandardTopLevelObject(stringFQName, "String"); standardClasses.declareStandardTopLevelObject(stringFQName, "String");
@@ -119,9 +119,7 @@ public class StaticContext {
@NotNull @NotNull
public JsName getGlobalName(@NotNull DeclarationDescriptor descriptor) { public JsName getGlobalName(@NotNull DeclarationDescriptor descriptor) {
JsName nameToDeclare = declarations.getName(descriptor); return declarations.getName(descriptor);
//nameToDeclare.setObfuscatable(false);
return nameToDeclare;
} }
public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) { public boolean isDeclared(@NotNull DeclarationDescriptor descriptor) {
@@ -3,6 +3,8 @@ package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil; import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetForExpression; import org.jetbrains.jet.lang.psi.JetForExpression;
import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.psi.JetParameter;
@@ -10,7 +12,9 @@ import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.reference.CallTranslator;
import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody; import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter; import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopParameter;
@@ -58,28 +62,22 @@ public final class ForTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression nextMethodInvocation(@NotNull TemporaryVariable iterator) { private JsExpression nextMethodInvocation(@NotNull TemporaryVariable iterator) {
return callStandardMethodOnExpression("next", iterator.nameReference()); FunctionDescriptor nextFunction = getNextFunction(context().bindingContext(), getLoopRange());
return CallTranslator.translate(iterator.nameReference(), nextFunction, context());
} }
@NotNull @NotNull
private JsExpression hasNextMethodInvocation(@NotNull TemporaryVariable iterator) { private JsExpression hasNextMethodInvocation(@NotNull TemporaryVariable iterator) {
return callStandardMethodOnExpression("hasNext", iterator.nameReference()); CallableDescriptor hasNextFunction = getHasNextCallable(context().bindingContext(), getLoopRange());
} return CallTranslator.translate(iterator.nameReference(), hasNextFunction, context());
@NotNull
private JsExpression callStandardMethodOnExpression(@NotNull String methodName, @NotNull JsNameRef expression) {
JsNameRef hasNext = AstUtil.newQualifiedNameRef(methodName);
AstUtil.setQualifier(hasNext, expression);
return AstUtil.newInvocation(hasNext);
} }
@NotNull @NotNull
private JsExpression iteratorMethodInvocation() { private JsExpression iteratorMethodInvocation() {
JetExpression rangeExpression = getLoopRange(); JetExpression rangeExpression = getLoopRange();
JsExpression range = Translation.translateAsExpression(rangeExpression, context()); JsExpression range = Translation.translateAsExpression(rangeExpression, context());
JsNameRef iteratorMethodReference = AstUtil.newQualifiedNameRef("iterator"); FunctionDescriptor iteratorFunction = getIteratorFunction(context().bindingContext(), rangeExpression);
AstUtil.setQualifier(iteratorMethodReference, range); return CallTranslator.translate(range, iteratorFunction, context());
return AstUtil.newInvocation(iteratorMethodReference);
} }
@NotNull @NotNull
@@ -126,6 +126,12 @@ public final class CallTranslator extends AbstractTranslator {
} }
} }
@NotNull
public static JsExpression translate(@NotNull JsExpression receiver, @NotNull CallableDescriptor functionDescriptor,
@NotNull TranslationContext context) {
return (new CallTranslator(receiver, Collections.<JsExpression>emptyList(), functionDescriptor, context)).translate();
}
@NotNull @NotNull
public static JsExpression translate(@NotNull JetUnaryExpression unaryExpression, public static JsExpression translate(@NotNull JetUnaryExpression unaryExpression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
@@ -173,14 +179,14 @@ public final class CallTranslator extends AbstractTranslator {
private final List<JsExpression> arguments; private final List<JsExpression> arguments;
@NotNull @NotNull
private final FunctionDescriptor functionDescriptor; private final CallableDescriptor descriptor;
private CallTranslator(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments, private CallTranslator(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) { @NotNull CallableDescriptor descriptor, @NotNull TranslationContext context) {
super(context); super(context);
this.receiver = receiver; this.receiver = receiver;
this.arguments = arguments; this.arguments = arguments;
this.functionDescriptor = descriptor; this.descriptor = descriptor;
} }
@NotNull @NotNull
@@ -206,12 +212,14 @@ public final class CallTranslator extends AbstractTranslator {
} }
private boolean isExtensionFunction() { private boolean isExtensionFunction() {
return DescriptorUtils.isExtensionFunction(functionDescriptor); return DescriptorUtils.isExtensionFunction(descriptor);
} }
@NotNull @NotNull
private JsExpression intrinsicInvocation() { private JsExpression intrinsicInvocation() {
FunctionIntrinsic functionIntrinsic = context().intrinsics().getFunctionIntrinsic(functionDescriptor); assert descriptor instanceof FunctionDescriptor;
FunctionIntrinsic functionIntrinsic =
context().intrinsics().getFunctionIntrinsic((FunctionDescriptor) descriptor);
assert receiver != null : "Functions that have functionIntrinsic implementation should have a receiver."; assert receiver != null : "Functions that have functionIntrinsic implementation should have a receiver.";
return functionIntrinsic.apply(receiver, arguments, context()); return functionIntrinsic.apply(receiver, arguments, context());
} }
@@ -222,25 +230,25 @@ public final class CallTranslator extends AbstractTranslator {
} }
private boolean isConstructor() { private boolean isConstructor() {
return isConstructorDescriptor(functionDescriptor); return isConstructorDescriptor(descriptor);
} }
private boolean isIntrinsic() { private boolean isIntrinsic() {
return context().intrinsics().isIntrinsic(functionDescriptor); return context().intrinsics().isIntrinsic(descriptor);
} }
@NotNull @NotNull
private JsExpression calleeReference() { private JsExpression calleeReference() {
if (DescriptorUtils.isVariableDescriptor(functionDescriptor)) { if (DescriptorUtils.isVariableDescriptor(descriptor)) {
//TODO: write tests on this cases //TODO: write tests on this cases
VariableDescriptor variableDescriptor = VariableDescriptor variableDescriptor =
getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) functionDescriptor); getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) descriptor);
if (variableDescriptor instanceof PropertyDescriptor) { if (variableDescriptor instanceof PropertyDescriptor) {
return getterCall((PropertyDescriptor) variableDescriptor); return getterCall((PropertyDescriptor) variableDescriptor);
} }
return qualifiedMethodReference(variableDescriptor); return qualifiedMethodReference(variableDescriptor);
} }
return qualifiedMethodReference(functionDescriptor); return qualifiedMethodReference(descriptor);
} }
@NotNull @NotNull
@@ -261,7 +269,7 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression extensionFunctionReference(@NotNull JsExpression methodReference) { private JsExpression extensionFunctionReference(@NotNull JsExpression methodReference) {
JsExpression qualifier = TranslationUtils.getExtensionFunctionImplicitReceiver(context(), functionDescriptor); JsExpression qualifier = TranslationUtils.getExtensionFunctionImplicitReceiver(context(), descriptor);
if (qualifier != null) { if (qualifier != null) {
AstUtil.setQualifier(methodReference, qualifier); AstUtil.setQualifier(methodReference, qualifier);
} }
@@ -270,7 +278,7 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression constructorCall() { private JsExpression constructorCall() {
JsNew constructorCall = new JsNew(qualifiedMethodReference(functionDescriptor)); JsNew constructorCall = new JsNew(qualifiedMethodReference(descriptor));
constructorCall.setArguments(arguments); constructorCall.setArguments(arguments);
return constructorCall; return constructorCall;
} }
@@ -22,13 +22,13 @@ import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isVariableDescr
* @author Pavel Talanov * @author Pavel Talanov
* <p/> * <p/>
* This class contains some code related to BindingContext use. Intention is not to pollute other classes. * This class contains some code related to BindingContext use. Intention is not to pollute other classes.
* Every call to BindingContext.get() is supposed to be wrapped by this utility class.
*/ */
public final class BindingUtils { public final class BindingUtils {
private BindingUtils() { private BindingUtils() {
} }
@NotNull @NotNull
static private <E extends PsiElement, D extends DeclarationDescriptor> static private <E extends PsiElement, D extends DeclarationDescriptor>
D getDescriptorForExpression(@NotNull BindingContext context, @NotNull E expression, Class<D> descriptorClass) { D getDescriptorForExpression(@NotNull BindingContext context, @NotNull E expression, Class<D> descriptorClass) {
@@ -298,4 +298,36 @@ public final class BindingUtils {
return defaultValue; return defaultValue;
} }
@NotNull
public static JetType getTypeForExpression(@NotNull BindingContext context,
@NotNull JetExpression expression) {
JetType jetType = context.get(BindingContext.EXPRESSION_TYPE, expression);
assert jetType != null : "Expression must have a type.";
return jetType;
}
@NotNull
public static FunctionDescriptor getIteratorFunction(@NotNull BindingContext context,
@NotNull JetExpression rangeExpression) {
FunctionDescriptor functionDescriptor = context.get(BindingContext.LOOP_RANGE_ITERATOR, rangeExpression);
assert functionDescriptor != null : "Range expression must have a descriptor for iterator function.";
return functionDescriptor;
}
@NotNull
public static FunctionDescriptor getNextFunction(@NotNull BindingContext context,
@NotNull JetExpression rangeExpression) {
FunctionDescriptor functionDescriptor = context.get(BindingContext.LOOP_RANGE_NEXT, rangeExpression);
assert functionDescriptor != null : "Range expression must have a descriptor for next function.";
return functionDescriptor;
}
@NotNull
public static CallableDescriptor getHasNextCallable(@NotNull BindingContext context,
@NotNull JetExpression rangeExpression) {
CallableDescriptor hasNextDescriptor = context.get(BindingContext.LOOP_RANGE_HAS_NEXT, rangeExpression);
assert hasNextDescriptor != null : "Range expression must have a descriptor for hasNext function or property.";
return hasNextDescriptor;
}
} }
@@ -35,7 +35,7 @@ public final class DescriptorUtils {
return (functionDescriptor.getName().equals(OperatorConventions.COMPARE_TO)); return (functionDescriptor.getName().equals(OperatorConventions.COMPARE_TO));
} }
public static boolean isConstructorDescriptor(@NotNull FunctionDescriptor descriptor) { public static boolean isConstructorDescriptor(@NotNull CallableDescriptor descriptor) {
return (descriptor instanceof ConstructorDescriptor); return (descriptor instanceof ConstructorDescriptor);
} }
@@ -71,7 +71,8 @@ public final class DescriptorUtils {
@NotNull String name) { @NotNull String name) {
Set<FunctionDescriptor> functionDescriptors = scope.getFunctions(name); Set<FunctionDescriptor> functionDescriptors = scope.getFunctions(name);
assert functionDescriptors.size() == 1 : assert functionDescriptors.size() == 1 :
"In scope " + scope + " supposed to be exactly one " + name + " function."; "In scope " + scope + " supposed to be exactly one " + name + " function.\n" +
"Found: " + functionDescriptors.size();
//noinspection LoopStatementThatDoesntLoop //noinspection LoopStatementThatDoesntLoop
for (FunctionDescriptor descriptor : functionDescriptors) { for (FunctionDescriptor descriptor : functionDescriptors) {
return descriptor; return descriptor;
@@ -122,7 +123,7 @@ public final class DescriptorUtils {
return containing; return containing;
} }
public static boolean isExtensionFunction(@NotNull FunctionDescriptor functionDescriptor) { public static boolean isExtensionFunction(@NotNull CallableDescriptor functionDescriptor) {
return (functionDescriptor.getReceiverParameter().exists()); return (functionDescriptor.getReceiverParameter().exists());
} }
@@ -4,6 +4,7 @@ import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil; import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
@@ -210,7 +211,7 @@ public final class TranslationUtils {
@Nullable @Nullable
public static JsExpression getExtensionFunctionImplicitReceiver(@NotNull TranslationContext context, public static JsExpression getExtensionFunctionImplicitReceiver(@NotNull TranslationContext context,
@NotNull FunctionDescriptor descriptor) { @NotNull CallableDescriptor descriptor) {
return getImplicitReceiverBasedOnOwner(context, descriptor); return getImplicitReceiverBasedOnOwner(context, descriptor);
} }
+44 -32
View File
@@ -16,7 +16,6 @@ function $A(iterable) {
} }
function keys(object) { function keys(object) {
if (Type(object) !== OBJECT_TYPE) { if (Type(object) !== OBJECT_TYPE) {
throw new TypeError(); throw new TypeError();
@@ -284,7 +283,7 @@ Kotlin.Array = Class.create({
iterator:function () { iterator:function () {
return new Kotlin.ArrayIterator(this); return new Kotlin.ArrayIterator(this);
}, },
indices:function() { indices:function () {
return new Kotlin.NumberRange(0, this.size(), false); return new Kotlin.NumberRange(0, this.size(), false);
} }
}); });
@@ -398,8 +397,20 @@ Kotlin.System = function () {
}; };
}(); }();
Kotlin.AbstractFunctionInvokationError = Class.create();
Kotlin.ArrayIterator = Class.create({ Kotlin.Iterator = Class.create({
initialize:function () {
},
next:function () {
throw new Kotlin.AbstractFunctionInvokationError();
},
hasNext:function () {
throw new Kotlin.AbstractFunctionInvokationError();
}
});
Kotlin.ArrayIterator = Class.create(Kotlin.Iterator, {
initialize:function (array) { initialize:function (array) {
this.array = array; this.array = array;
this.index = 0; this.index = 0;
@@ -412,36 +423,37 @@ Kotlin.ArrayIterator = Class.create({
} }
}); });
Kotlin.RangeIterator = Kotlin.Class.create({initialize:function (start, count, reversed) { Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, {
this.$start = start; initialize:function (start, count, reversed) {
this.$count = count; this.$start = start;
this.$reversed = reversed; this.$count = count;
this.$i = this.get_start(); this.$reversed = reversed;
}, get_start:function () { this.$i = this.get_start();
return this.$start; }, get_start:function () {
}, get_count:function () { return this.$start;
return this.$count; }, get_count:function () {
}, set_count:function (tmp$0) { return this.$count;
this.$count = tmp$0; }, set_count:function (tmp$0) {
}, get_reversed:function () { this.$count = tmp$0;
return this.$reversed; }, get_reversed:function () {
}, get_i:function () { return this.$reversed;
return this.$i; }, get_i:function () {
}, set_i:function (tmp$0) { return this.$i;
this.$i = tmp$0; }, set_i:function (tmp$0) {
}, next:function () { this.$i = tmp$0;
this.set_count(this.get_count() - 1); }, next:function () {
if (this.get_reversed()) { this.set_count(this.get_count() - 1);
this.set_i(this.get_i() - 1); if (this.get_reversed()) {
return this.get_i() + 1; this.set_i(this.get_i() - 1);
return this.get_i() + 1;
}
else {
this.set_i(this.get_i() + 1);
return this.get_i() - 1;
}
}, hasNext:function () {
return this.get_count() > 0;
} }
else {
this.set_i(this.get_i() + 1);
return this.get_i() - 1;
}
}, hasNext:function () {
return this.get_count() > 0;
}
}); });
Kotlin.NumberRange = Kotlin.Class.create({initialize:function (start, size, reversed) { Kotlin.NumberRange = Kotlin.Class.create({initialize:function (start, size, reversed) {