KT-11030 Implements local classes that don't have closure

This commit is contained in:
Alexey Andreev
2016-03-02 16:49:47 +03:00
parent 7ca6102cac
commit 1f8c3375fe
5 changed files with 67 additions and 9 deletions
@@ -16,11 +16,7 @@
package org.jetbrains.kotlin.js.translate.context
import com.google.dart.compiler.backend.js.ast.JsExpression
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer
import com.google.dart.compiler.backend.js.ast.JsNameRef
import com.google.dart.compiler.backend.js.ast.JsObjectScope
import com.google.dart.compiler.backend.js.ast.JsFunction
import com.google.dart.compiler.backend.js.ast.*
import com.google.dart.compiler.backend.js.ast.metadata.staticRef
class DefinitionPlace(
@@ -28,9 +24,9 @@ class DefinitionPlace(
private val fqName: JsExpression,
val properties: MutableList<JsPropertyInitializer>
) {
fun define(suggestedName: String, expression : JsExpression): JsNameRef {
val name = scope.declareFreshName(suggestedName)
fun define(suggestedName: String, expression : JsExpression) = define(scope.declareFreshName(suggestedName), expression)
fun define(name: JsName, expression: JsExpression): JsNameRef {
if (expression is JsFunction) {
/** JsInliner should be able
* to find function by name */
@@ -38,6 +38,9 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.*;
@@ -255,6 +258,29 @@ public final class StaticContext {
}
};
Rule<JsName> localDeclarations = new Rule<JsName>() {
@Nullable
@Override
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
if (!DescriptorUtils.isLocal(descriptor) || !DescriptorUtils.isClass(descriptor)) return null;
List<String> parts = new ArrayList<String>();
do {
parts.add(descriptor.getName().asString());
descriptor = descriptor.getContainingDeclaration();
} while (!(descriptor instanceof ClassOrPackageFragmentDescriptor));
Collections.reverse(parts);
StringBuilder suggestedName = new StringBuilder(parts.get(0));
for (int i = 1; i < parts.size(); ++i) {
suggestedName.append('$').append(parts.get(i));
}
JsScope scope = getScopeForDescriptor(descriptor);
return scope.declareFreshName(suggestedName.toString());
}
};
Rule<JsName> namesForStandardClasses = new Rule<JsName>() {
@Override
@Nullable
@@ -368,6 +394,7 @@ public final class StaticContext {
};
addRule(namesForDynamic);
addRule(localDeclarations);
addRule(namesForStandardClasses);
addRule(constructorOrCompanionObjectHasTheSameNameAsTheClass);
addRule(propertyOrPropertyAccessor);
@@ -554,6 +581,9 @@ public final class StaticContext {
return null;
}
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (container != null && !(container instanceof ClassDescriptor)) {
container = DescriptorUtils.getContainingClass(container);
}
if (container == null) {
return null;
}
@@ -574,6 +604,22 @@ public final class StaticContext {
}
};
Rule<JsExpression> localClassesHavePackageQualifier = new Rule<JsExpression>() {
@Nullable
@Override
public JsExpression apply(@NotNull DeclarationDescriptor descriptor) {
if (!DescriptorUtils.isLocal(descriptor) || !(descriptor instanceof ClassDescriptor)) return null;
descriptor = descriptor.getContainingDeclaration();
while (descriptor != null && !(descriptor instanceof ClassOrPackageFragmentDescriptor)) {
descriptor = descriptor.getContainingDeclaration();
}
if (!(descriptor instanceof PackageFragmentDescriptor)) return null;
return getQualifiedReference(descriptor);
}
};
addRule(libraryObjectsHaveKotlinQualifier);
addRule(constructorOrCompanionObjectHasTheSameQualifierAsTheClass);
addRule(standardObjectsHaveKotlinQualifier);
@@ -581,6 +627,7 @@ public final class StaticContext {
addRule(nativeObjectsHaveNativePartOfFullQualifier);
addRule(staticMembersHaveContainerQualifier);
addRule(nestedClassesHaveContainerQualifier);
addRule(localClassesHavePackageQualifier);
}
}
@@ -399,10 +399,15 @@ public class TranslationContext {
@NotNull
public JsNameRef define(DeclarationDescriptor descriptor, JsExpression expression) {
String suggestedName = TranslationUtils.getSuggestedNameForInnerDeclaration(this, descriptor);
String suggestedName = TranslationUtils.getSuggestedNameForInnerDeclaration(staticContext, descriptor);
return getDefinitionPlace().define(suggestedName, expression);
}
@NotNull
public JsNameRef define(JsName name, JsExpression expression) {
return getDefinitionPlace().define(name, expression);
}
@Nullable
private JsNameRef captureIfNeedAndGetCapturedName(DeclarationDescriptor descriptor) {
if (usageTracker != null) {
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
import org.jetbrains.kotlin.js.translate.operation.BinaryOperationTranslator;
import org.jetbrains.kotlin.js.translate.operation.UnaryOperationTranslator;
import org.jetbrains.kotlin.js.translate.reference.*;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -565,4 +566,12 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
assert descriptor != null : "Missing declaration descriptor: " + PsiUtilsKt.getTextWithLocation(expression);
return descriptor;
}
@Override
public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
JsInvocation jsClass = ClassTranslator.generateClassCreation(klass, context);
DeclarationDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
JsName name = context.getNameForDescriptor(descriptor);
return context.define(name, jsClass);
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.StaticContext;
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.Translation;
@@ -263,7 +264,7 @@ public final class TranslationUtils {
}
@NotNull
public static String getSuggestedNameForInnerDeclaration(TranslationContext context, DeclarationDescriptor descriptor) {
public static String getSuggestedNameForInnerDeclaration(StaticContext context, DeclarationDescriptor descriptor) {
String suggestedName = "";
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
//noinspection ConstantConditions