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.jet.lang.descriptors.*;
import java.util.Set;
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.getNameForNamespace;
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,
@NotNull String name) {
JsName jsName = context.getScope().declareVariable(descriptor, name, shouldObfuscate);
jsName.setObfuscatable(false);
declarations.putName(descriptor, jsName);
declarations.putQualifier(descriptor, context.getQualifier());
return jsName;
@@ -85,11 +88,27 @@ public final class DeclarationVisitor extends DeclarationDescriptorVisitor<Void,
@Override
public Void visitFunctionDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull DeclarationContext context) {
boolean overridesDeclaredDescriptor = declareAsOverridden(descriptor, context);
if (overridesDeclaredDescriptor) {
return null;
}
declareName(descriptor, context);
declareScope(descriptor, context, "function " + descriptor.getName());
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
public Void visitPropertyDescriptor(@NotNull PropertyDescriptor descriptor, @NotNull DeclarationContext context) {
String propertyName = descriptor.getName();
@@ -33,9 +33,16 @@ public final class StandardClasses {
declareJavaArrayList(standardClasses);
declareJavaSystem(standardClasses);
declareJavaInteger(standardClasses);
declareJavaUtilIterator(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) {
String stringFQName = "jet.String";
standardClasses.declareStandardTopLevelObject(stringFQName, "String");
@@ -119,9 +119,7 @@ public class StaticContext {
@NotNull
public JsName getGlobalName(@NotNull DeclarationDescriptor descriptor) {
JsName nameToDeclare = declarations.getName(descriptor);
//nameToDeclare.setObfuscatable(false);
return nameToDeclare;
return declarations.getName(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.util.AstUtil;
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.JetForExpression;
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.general.AbstractTranslator;
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.getLoopParameter;
@@ -58,28 +62,22 @@ public final class ForTranslator extends AbstractTranslator {
@NotNull
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
private JsExpression hasNextMethodInvocation(@NotNull TemporaryVariable iterator) {
return callStandardMethodOnExpression("hasNext", iterator.nameReference());
}
@NotNull
private JsExpression callStandardMethodOnExpression(@NotNull String methodName, @NotNull JsNameRef expression) {
JsNameRef hasNext = AstUtil.newQualifiedNameRef(methodName);
AstUtil.setQualifier(hasNext, expression);
return AstUtil.newInvocation(hasNext);
CallableDescriptor hasNextFunction = getHasNextCallable(context().bindingContext(), getLoopRange());
return CallTranslator.translate(iterator.nameReference(), hasNextFunction, context());
}
@NotNull
private JsExpression iteratorMethodInvocation() {
JetExpression rangeExpression = getLoopRange();
JsExpression range = Translation.translateAsExpression(rangeExpression, context());
JsNameRef iteratorMethodReference = AstUtil.newQualifiedNameRef("iterator");
AstUtil.setQualifier(iteratorMethodReference, range);
return AstUtil.newInvocation(iteratorMethodReference);
FunctionDescriptor iteratorFunction = getIteratorFunction(context().bindingContext(), rangeExpression);
return CallTranslator.translate(range, iteratorFunction, context());
}
@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
public static JsExpression translate(@NotNull JetUnaryExpression unaryExpression,
@NotNull TranslationContext context) {
@@ -173,14 +179,14 @@ public final class CallTranslator extends AbstractTranslator {
private final List<JsExpression> arguments;
@NotNull
private final FunctionDescriptor functionDescriptor;
private final CallableDescriptor descriptor;
private CallTranslator(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments,
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
@NotNull CallableDescriptor descriptor, @NotNull TranslationContext context) {
super(context);
this.receiver = receiver;
this.arguments = arguments;
this.functionDescriptor = descriptor;
this.descriptor = descriptor;
}
@NotNull
@@ -206,12 +212,14 @@ public final class CallTranslator extends AbstractTranslator {
}
private boolean isExtensionFunction() {
return DescriptorUtils.isExtensionFunction(functionDescriptor);
return DescriptorUtils.isExtensionFunction(descriptor);
}
@NotNull
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.";
return functionIntrinsic.apply(receiver, arguments, context());
}
@@ -222,25 +230,25 @@ public final class CallTranslator extends AbstractTranslator {
}
private boolean isConstructor() {
return isConstructorDescriptor(functionDescriptor);
return isConstructorDescriptor(descriptor);
}
private boolean isIntrinsic() {
return context().intrinsics().isIntrinsic(functionDescriptor);
return context().intrinsics().isIntrinsic(descriptor);
}
@NotNull
private JsExpression calleeReference() {
if (DescriptorUtils.isVariableDescriptor(functionDescriptor)) {
if (DescriptorUtils.isVariableDescriptor(descriptor)) {
//TODO: write tests on this cases
VariableDescriptor variableDescriptor =
getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) functionDescriptor);
getVariableDescriptorForVariableAsFunction((VariableAsFunctionDescriptor) descriptor);
if (variableDescriptor instanceof PropertyDescriptor) {
return getterCall((PropertyDescriptor) variableDescriptor);
}
return qualifiedMethodReference(variableDescriptor);
}
return qualifiedMethodReference(functionDescriptor);
return qualifiedMethodReference(descriptor);
}
@NotNull
@@ -261,7 +269,7 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
private JsExpression extensionFunctionReference(@NotNull JsExpression methodReference) {
JsExpression qualifier = TranslationUtils.getExtensionFunctionImplicitReceiver(context(), functionDescriptor);
JsExpression qualifier = TranslationUtils.getExtensionFunctionImplicitReceiver(context(), descriptor);
if (qualifier != null) {
AstUtil.setQualifier(methodReference, qualifier);
}
@@ -270,7 +278,7 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
private JsExpression constructorCall() {
JsNew constructorCall = new JsNew(qualifiedMethodReference(functionDescriptor));
JsNew constructorCall = new JsNew(qualifiedMethodReference(descriptor));
constructorCall.setArguments(arguments);
return constructorCall;
}
@@ -22,13 +22,13 @@ import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isVariableDescr
* @author Pavel Talanov
* <p/>
* 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 {
private BindingUtils() {
}
@NotNull
static private <E extends PsiElement, D extends DeclarationDescriptor>
D getDescriptorForExpression(@NotNull BindingContext context, @NotNull E expression, Class<D> descriptorClass) {
@@ -298,4 +298,36 @@ public final class BindingUtils {
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));
}
public static boolean isConstructorDescriptor(@NotNull FunctionDescriptor descriptor) {
public static boolean isConstructorDescriptor(@NotNull CallableDescriptor descriptor) {
return (descriptor instanceof ConstructorDescriptor);
}
@@ -71,7 +71,8 @@ public final class DescriptorUtils {
@NotNull String name) {
Set<FunctionDescriptor> functionDescriptors = scope.getFunctions(name);
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
for (FunctionDescriptor descriptor : functionDescriptors) {
return descriptor;
@@ -122,7 +123,7 @@ public final class DescriptorUtils {
return containing;
}
public static boolean isExtensionFunction(@NotNull FunctionDescriptor functionDescriptor) {
public static boolean isExtensionFunction(@NotNull CallableDescriptor functionDescriptor) {
return (functionDescriptor.getReceiverParameter().exists());
}
@@ -4,6 +4,7 @@ import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
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.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
@@ -210,7 +211,7 @@ public final class TranslationUtils {
@Nullable
public static JsExpression getExtensionFunctionImplicitReceiver(@NotNull TranslationContext context,
@NotNull FunctionDescriptor descriptor) {
@NotNull CallableDescriptor descriptor) {
return getImplicitReceiverBasedOnOwner(context, descriptor);
}
+44 -32
View File
@@ -16,7 +16,6 @@ function $A(iterable) {
}
function keys(object) {
if (Type(object) !== OBJECT_TYPE) {
throw new TypeError();
@@ -284,7 +283,7 @@ Kotlin.Array = Class.create({
iterator:function () {
return new Kotlin.ArrayIterator(this);
},
indices:function() {
indices:function () {
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) {
this.array = array;
this.index = 0;
@@ -412,36 +423,37 @@ Kotlin.ArrayIterator = Class.create({
}
});
Kotlin.RangeIterator = Kotlin.Class.create({initialize:function (start, count, reversed) {
this.$start = start;
this.$count = count;
this.$reversed = reversed;
this.$i = this.get_start();
}, get_start:function () {
return this.$start;
}, get_count:function () {
return this.$count;
}, set_count:function (tmp$0) {
this.$count = tmp$0;
}, get_reversed:function () {
return this.$reversed;
}, get_i:function () {
return this.$i;
}, set_i:function (tmp$0) {
this.$i = tmp$0;
}, next:function () {
this.set_count(this.get_count() - 1);
if (this.get_reversed()) {
this.set_i(this.get_i() - 1);
return this.get_i() + 1;
Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, {
initialize:function (start, count, reversed) {
this.$start = start;
this.$count = count;
this.$reversed = reversed;
this.$i = this.get_start();
}, get_start:function () {
return this.$start;
}, get_count:function () {
return this.$count;
}, set_count:function (tmp$0) {
this.$count = tmp$0;
}, get_reversed:function () {
return this.$reversed;
}, get_i:function () {
return this.$i;
}, set_i:function (tmp$0) {
this.$i = tmp$0;
}, next:function () {
this.set_count(this.get_count() - 1);
if (this.get_reversed()) {
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) {