JS: fix inlining in a new flat JS generator

This commit is contained in:
Alexey Andreev
2016-10-17 16:24:02 +03:00
parent e13d34e08d
commit 20396b0e5f
257 changed files with 384 additions and 4228 deletions
@@ -1173,7 +1173,7 @@ fun main(args: Array<String>) {
}
}
generateTestDataForReservedWords()
//generateTestDataForReservedWords()
testGroup("js/js.tests/test", "js/js.translator/testData") {
testClass<AbstractBoxJsTest>() {
@@ -64,7 +64,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
public static JsProgram process(@NotNull TranslationContext context) {
JsProgram program = context.program();
IdentityHashMap<JsName, JsFunction> functions = CollectUtilsKt.collectNamedFunctions(program);
Map<JsName, JsFunction> functions = CollectUtilsKt.collectNamedFunctions(program);
JsInliner inliner = new JsInliner(functions, new FunctionReader(context), context.bindingTrace());
inliner.accept(program);
RemoveUnusedFunctionDefinitionsKt.removeUnusedFunctionDefinitions(program, functions);
@@ -22,6 +22,7 @@ import com.google.dart.compiler.backend.js.ast.metadata.staticRef
import org.jetbrains.kotlin.js.inline.util.collectors.InstanceCollector
import org.jetbrains.kotlin.js.inline.util.collectors.PropertyCollector
import org.jetbrains.kotlin.js.translate.expression.*
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import java.util.*
fun collectFunctionReferencesInside(scope: JsNode): List<JsName> =
@@ -133,19 +134,54 @@ fun collectJsProperties(scope: JsNode): IdentityHashMap<JsName, JsExpression> {
return collector.properties
}
fun collectNamedFunctions(scope: JsNode): IdentityHashMap<JsName, JsFunction> {
val namedFunctions = IdentityHashMap<JsName, JsFunction>()
fun collectNamedFunctions(scope: JsNode) = collectNamedFunctionsAndMetadata(scope).mapValues { it.value.first }
for ((name, value) in collectJsProperties(scope)) {
val function: JsFunction? = when (value) {
is JsFunction -> value
else -> InlineMetadata.decompose(value)?.function
fun collectNamedFunctionsOrMetadata(scope: JsNode) = collectNamedFunctionsAndMetadata(scope).mapValues { it.value.second }
fun collectNamedFunctionsAndMetadata(scope: JsNode): Map<JsName, Pair<JsFunction, JsExpression>> {
val namedFunctions = mutableMapOf<JsName, Pair<JsFunction, JsExpression>>()
scope.accept(object : RecursiveJsVisitor() {
override fun visitBinaryExpression(x: JsBinaryOperation) {
val assignment = JsAstUtils.decomposeAssignment(x)
if (assignment != null) {
val (left, right) = assignment
if (left is JsNameRef) {
val name = left.name
val function = extractFunction(right)
if (function != null && name != null) {
namedFunctions[name] = Pair(function, right)
}
}
}
super.visitBinaryExpression(x)
}
if (function != null) {
namedFunctions[name] = function
override fun visit(x: JsVars.JsVar) {
val initializer = x.initExpression
val name = x.name
if (initializer != null && name != null) {
val function = extractFunction(initializer)
if (function != null) {
namedFunctions[name] = Pair(function, initializer)
}
}
super.visit(x)
}
}
override fun visitFunction(x: JsFunction) {
val name = x.name
if (name != null) {
namedFunctions[name] = Pair(x, x)
}
super.visitFunction(x)
}
private fun extractFunction(expression: JsExpression) = when (expression) {
is JsFunction -> expression
else -> InlineMetadata.decompose(expression)?.function
}
})
return namedFunctions
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.inline.util.collectors
import com.google.dart.compiler.backend.js.ast.*
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import java.util.IdentityHashMap
+12 -2
View File
@@ -16,9 +16,19 @@
package kotlin
open class Error(message: String? = null) : Throwable(message, null) {}
open class Error(message: String? = null) : Throwable(message, null) {
init {
val self: dynamic = this
self.message = message
}
}
open class Exception(message: String? = null) : Throwable(message, null) {}
open class Exception(message: String? = null) : Throwable(message, null) {
init {
val self: dynamic = this
self.message = message
}
}
open class RuntimeException(message: String? = null) : Exception(message) {}
File diff suppressed because it is too large Load Diff
@@ -22,6 +22,7 @@ import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.inline.util.CollectUtilsKt;
import java.util.Map;
@@ -43,6 +44,13 @@ public class AstSearchUtil {
return property;
}
@NotNull
public static JsExpression getMetadataOrFunction(@NotNull JsNode searchRoot, @NotNull String name) {
JsExpression property = findByIdent(CollectUtilsKt.collectNamedFunctionsOrMetadata(searchRoot), name);
assert property != null: "Property `" + name + "` was not found";
return property;
}
@Nullable
private static <T extends JsExpression> T findByIdent(@NotNull Map<JsName, T> properties, @NotNull String name) {
for (Map.Entry<JsName, T> entry : properties.entrySet()) {
@@ -94,7 +94,7 @@ public class DirectiveTestUtils {
@NotNull
String getFunctionCode(@NotNull JsNode ast, @NotNull String functionName) {
JsFunction function = AstSearchUtil.getFunction(ast, functionName);
return function.toString();
return function.getBody().toString();
}
@NotNull
@@ -213,7 +213,7 @@ public class DirectiveTestUtils {
@Override
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
String functionName = arguments.getPositionalArgument(0);
JsExpression property = AstSearchUtil.getProperty(ast, functionName);
JsExpression property = AstSearchUtil.getMetadataOrFunction(ast, functionName);
String message = "Inline metadata has not been generated for function " + functionName;
assertNotNull(message, InlineMetadata.decompose(property));
}
@@ -223,7 +223,7 @@ public class DirectiveTestUtils {
@Override
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
String functionName = arguments.getPositionalArgument(0);
JsExpression property = AstSearchUtil.getProperty(ast, functionName);
JsExpression property = AstSearchUtil.getMetadataOrFunction(ast, functionName);
String message = "Inline metadata has been generated for not effectively public function " + functionName;
assertTrue(message, property instanceof JsFunction);
}
@@ -49,7 +49,7 @@ fun CallInfo.isSuperInvocation(): Boolean {
val CallInfo.calleeOwner: JsExpression
get() {
val calleeOwner = resolvedCall.resultingDescriptor.containingDeclaration
return ReferenceTranslator.translateAsFQReference(calleeOwner, context)
return ReferenceTranslator.translateAsValueReference(calleeOwner, context)
}
val VariableAccessInfo.variableDescriptor: VariableDescriptor
@@ -81,7 +81,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
return JsInvocation(JsNameRef(context.getNameForDescriptor(callableDescriptor)), argumentsInfo.translateArguments)
}
val functionRef = ReferenceTranslator.translateAsFQReference(callableDescriptor, context)
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
return JsInvocation(functionRef, argumentsInfo.translateArguments)
}
@@ -101,7 +101,7 @@ object DefaultFunctionCallCase : FunctionCallCase() {
return JsInvocation(JsNameRef(functionName, extensionReceiver), argumentsInfo.translateArguments)
}
val functionRef = ReferenceTranslator.translateAsFQReference(callableDescriptor, context)
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
val referenceToCall =
if (callableDescriptor.visibility == Visibilities.LOCAL) {
@@ -212,7 +212,7 @@ object ConstructorCallCase : FunctionCallCase() {
private inline fun FunctionCallInfo.doTranslate(
getArguments: CallArgumentTranslator.ArgumentsInfo.() -> List<JsExpression>
): JsExpression {
val functionRef = ReferenceTranslator.translateAsFQReference(callableDescriptor, context)
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
val invocationArguments = mutableListOf<JsExpression>()
val constructorDescriptor = callableDescriptor as ClassConstructorDescriptor
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
@@ -84,17 +85,7 @@ object DefaultVariableAccessCase : VariableAccessCase() {
return JsInvocation(pureFqn(context.getNameForObjectInstance (descriptor.getReferencedObject()), null))
}
val functionRef = context.aliasOrValue(callableDescriptor) {
if (context.isFromCurrentModule(variableDescriptor)) {
context.getInnerReference(variableDescriptor)
}
else {
val qualifier = context.getInnerReference(variableDescriptor.containingDeclaration)
val name = context.getNameForDescriptor(variableDescriptor)
JsNameRef(name, qualifier)
}
}
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
val ref = if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) {
getCapturedVarAccessor(functionRef)
}
@@ -170,7 +161,8 @@ object SuperPropertyAccessCase : VariableAccessCase() {
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldAccessViaFunctions(descriptor)) {
val accessor = getAccessDescriptorIfNeeded()
val prototype = pureFqn(Namer.getPrototypeName(), context.getInnerReference(descriptor.containingDeclaration))
val containingRef = ReferenceTranslator.translateAsValueReference(descriptor.containingDeclaration, context)
val prototype = pureFqn(Namer.getPrototypeName(), containingRef)
val funRef = Namer.getFunctionCallRef(pureFqn(context.getNameForDescriptor(accessor), prototype))
val arguments = listOf(dispatchReceiver!!) + additionalArguments
JsInvocation(funRef, *arguments.toTypedArray())
@@ -153,6 +153,9 @@ public final class StaticContext {
@NotNull
private final JsObjectLiteral exportObject = rootPackage.objectLiteral;
@NotNull
private final Set<MemberDescriptor> exportedDeclarations = new HashSet<MemberDescriptor>();
//TODO: too many parameters in constructor
private StaticContext(
@NotNull JsProgram program,
@@ -527,7 +530,9 @@ public final class StaticContext {
return null;
}
if (getSuperclass((ClassDescriptor) descriptor) == null) {
return rootFunction.getScope();
JsFunction function = new JsFunction(rootFunction.getScope(), new JsBlock(), descriptor.toString());
scopeToFunction.put(function.getScope(), function);
return function.getScope();
}
return null;
}
@@ -555,8 +560,7 @@ public final class StaticContext {
Rule<JsScope> generateInnerScopesForMembers = new Rule<JsScope>() {
@Override
public JsScope apply(@NotNull DeclarationDescriptor descriptor) {
JsScope enclosingScope = getEnclosingScope(descriptor);
return enclosingScope.innerObjectScope("Scope for member " + descriptor.getName());
return rootFunction.getScope().innerObjectScope("Scope for member " + descriptor.getName());
}
};
Rule<JsScope> createFunctionObjectsForCallableDescriptors = new Rule<JsScope>() {
@@ -659,27 +663,40 @@ public final class StaticContext {
classes.add(classDescriptor);
}
public void export(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (descriptor instanceof ConstructorDescriptor) {
ConstructorDescriptor constructor = (ConstructorDescriptor) descriptor;
container = constructor.getConstructedClass().getContainingDeclaration();
}
if (!(container instanceof PackageFragmentDescriptor)) {
throw new IllegalArgumentException("Declaration " + descriptor + " is not a top-level declaration");
}
public void export(@NotNull MemberDescriptor descriptor, boolean force) {
if (exportedDeclarations.contains(descriptor)) return;
PackageFragmentDescriptor packageDescriptor = (PackageFragmentDescriptor) container;
ExportedPackage exportedPackage = rootPackage;
for (Name packageName : packageDescriptor.getFqName().pathSegments()) {
exportedPackage = exportedPackage.getSubpackage(packageName.asString());
}
if (descriptor instanceof ConstructorDescriptor && ((ConstructorDescriptor) descriptor).isPrimary()) return;
JsExpression initializerExpr = DeclarationExporter.exportDeclaration(this, descriptor, exportStatements);
if (initializerExpr != null) {
JsPropertyInitializer initializer = new JsPropertyInitializer(
getNameForDescriptor(descriptor).makeRef(), initializerExpr);
exportedPackage.objectLiteral.getPropertyInitializers().add(initializer);
SuggestedName suggestedName = nameSuggestion.suggest(descriptor);
if (suggestedName == null) return;
DeclarationDescriptor container = suggestedName.getScope();
if (!DeclarationExporter.shouldBeExported(descriptor, force)) return;
exportedDeclarations.add(descriptor);
if (container instanceof PackageFragmentDescriptor) {
PackageFragmentDescriptor packageDescriptor = (PackageFragmentDescriptor) container;
ExportedPackage exportedPackage = rootPackage;
for (Name packageName : packageDescriptor.getFqName().pathSegments()) {
exportedPackage = exportedPackage.getSubpackage(packageName.asString());
}
JsExpression initializerExpr = DeclarationExporter.exportDeclaration(this, descriptor, exportStatements);
if (initializerExpr != null) {
JsName propertyName = getNameForDescriptor(descriptor);
if (MetadataProperties.getStaticRef(propertyName) == null) {
if (!(initializerExpr instanceof JsNameRef) || ((JsNameRef) initializerExpr).getName() != propertyName) {
MetadataProperties.setStaticRef(propertyName, initializerExpr);
}
}
JsPropertyInitializer initializer = new JsPropertyInitializer(propertyName.makeRef(), initializerExpr);
exportedPackage.objectLiteral.getPropertyInitializers().add(initializer);
}
}
else {
JsExpression initializerExpr = DeclarationExporter.exportDeclaration(this, descriptor, exportStatements);
assert initializerExpr == null : "Should not produce initializer for non-package declaration";
}
}
@@ -698,11 +715,12 @@ public final class StaticContext {
rootFunction.getBody().getStatements().addAll(importStatements);
addClassPrototypes();
rootFunction.getBody().getStatements().addAll(declarationStatements);
rootFunction.getBody().getStatements().addAll(topLevelStatements);
JsName rootPackageName = rootFunction.getScope().declareName(Namer.getRootPackageName());
rootFunction.getBody().getStatements().add(JsAstUtils.newVar(rootPackageName, exportObject));
rootFunction.getBody().getStatements().addAll(exportStatements);
rootFunction.getBody().getStatements().addAll(topLevelStatements);
}
private void addClassPrototypes() {
@@ -236,6 +236,9 @@ public class TranslationContext {
@NotNull
public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof MemberDescriptor && isFromCurrentModule(descriptor) && isPublicInlineFunction()) {
staticContext.export((MemberDescriptor) descriptor, true);
}
return staticContext.getQualifiedReference(descriptor);
}
@@ -608,14 +611,20 @@ public class TranslationContext {
staticContext.addClass(classDescriptor);
}
public void export(@NotNull DeclarationDescriptor descriptor) {
staticContext.export(descriptor);
public void export(@NotNull MemberDescriptor descriptor) {
staticContext.export(descriptor, false);
}
public boolean isFromCurrentModule(@NotNull DeclarationDescriptor descriptor) {
return staticContext.getCurrentModule() == DescriptorUtilsKt.getModule(descriptor);
}
public boolean isPublicInlineFunction() {
if (!(declarationDescriptor instanceof FunctionDescriptor)) return false;
FunctionDescriptor function = (FunctionDescriptor) declarationDescriptor;
return function.isInline() && DescriptorUtilsKt.isEffectivelyPublicApi(function);
}
@NotNull
public ModuleDescriptor getCurrentModule() {
return staticContext.getCurrentModule();
@@ -19,39 +19,81 @@ package org.jetbrains.kotlin.js.translate.context
import com.google.dart.compiler.backend.js.ast.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
fun StaticContext.exportDeclaration(declaration: DeclarationDescriptor, additionalStatements: MutableList<in JsStatement>): JsExpression? {
// TODO: refactor
fun StaticContext.exportDeclaration(declaration: MemberDescriptor, additionalStatements: MutableList<in JsStatement>): JsExpression? {
val scope = nameSuggestion.suggest(declaration)!!.scope
return when {
declaration is ClassDescriptor && declaration.kind == ClassKind.OBJECT -> {
exportObject(declaration, additionalStatements)
null
declaration is ClassDescriptor -> when {
declaration.kind == ClassKind.OBJECT || declaration.kind == ClassKind.ENUM_ENTRY -> {
exportObject(declaration, scope, additionalStatements)
null
}
scope is ClassDescriptor -> {
exportNested(declaration, scope, additionalStatements)
null
}
else -> {
getInnerNameForDescriptor(declaration).makeRef()
}
}
declaration is PropertyDescriptor -> {
exportProperty(declaration, additionalStatements)
if (scope is PackageFragmentDescriptor) {
exportProperty(declaration, scope, additionalStatements)
}
null
}
else -> {
scope is PackageFragmentDescriptor -> {
getInnerNameForDescriptor(declaration).makeRef()
}
else -> null
}
}
private fun StaticContext.exportObject(declaration: ClassDescriptor, additionalStatements: MutableList<in JsStatement>) {
val suggestedName = nameSuggestion.suggest(declaration)!!
val qualifier = getQualifiedReference(suggestedName.scope)
fun MemberDescriptor.shouldBeExported(force: Boolean) =
force || isEffectivelyPublicApi || AnnotationsUtils.getJsNameAnnotation(this) != null
private fun StaticContext.exportNested(
descriptor: ClassDescriptor,
scope: ClassDescriptor,
additionalStatements: MutableList<in JsStatement>
) {
val qualifier = getBaseReference(scope)
val reference = JsAstUtils.pureFqn(getNameForDescriptor(descriptor), qualifier)
val instanceRef = JsAstUtils.pureFqn(getInnerNameForDescriptor(descriptor), null)
additionalStatements += JsAstUtils.assignment(reference, instanceRef).makeStmt()
}
private fun StaticContext.exportObject(
declaration: ClassDescriptor,
scope: DeclarationDescriptor,
additionalStatements: MutableList<in JsStatement>
) {
val qualifier = getBaseReference(scope)
val name = getNameForDescriptor(declaration)
additionalStatements += JsAstUtils.defineGetter(program, qualifier, name.ident, getNameForObjectInstance(declaration).makeRef())
}
private fun StaticContext.exportProperty(declaration: PropertyDescriptor, additionalStatements: MutableList<in JsStatement>) {
private fun StaticContext.getBaseReference(declaration: DeclarationDescriptor) = when (declaration) {
is PackageFragmentDescriptor -> getQualifiedReference(declaration)
else -> JsAstUtils.pureFqn(getInnerNameForDescriptor(declaration), null)
}
private fun StaticContext.exportProperty(
declaration: PropertyDescriptor,
scope: DeclarationDescriptor,
additionalStatements: MutableList<in JsStatement>
) {
val propertyLiteral = JsObjectLiteral(true)
val suggestedName = nameSuggestion.suggest(declaration)!!
val qualifier = getQualifiedReference(suggestedName.scope)
val qualifier = getBaseReference(scope)
val name = getNameForDescriptor(declaration).ident
val getterBody: JsExpression = if (JsDescriptorUtils.isSimpleFinalProperty(declaration)) {
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.js.translate.context.*
import org.jetbrains.kotlin.js.translate.expression.FunctionTranslator
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getPropertyDescriptorForConstructorParameter
@@ -301,7 +302,7 @@ class ClassTranslator private constructor(
val name = nonConstructorUsageTracker.getNameForCapturedDescriptor(it)!!
JsAstUtils.pureFqn(name, closureQualifier)
}
callSite.invocationArgs.addAll(0, closureArgs.toList())
callSite.invocationArgs.addAll(0, closureArgs)
}
}
}
@@ -340,7 +341,7 @@ class ClassTranslator private constructor(
if (supertypes.size == 1) {
val type = supertypes[0]
val supertypeDescriptor = getClassDescriptorForType(type)
return listOf(context().getInnerReference(supertypeDescriptor))
return listOf(ReferenceTranslator.translateAsTypeReference(supertypeDescriptor, context()))
}
val supertypeConstructors = mutableSetOf<TypeConstructor>()
@@ -356,7 +357,7 @@ class ClassTranslator private constructor(
for (typeConstructor in sortedAllSuperTypes) {
if (supertypeConstructors.contains(typeConstructor)) {
val supertypeDescriptor = getClassDescriptorForTypeConstructor(typeConstructor)
supertypesRefs += context().getInnerReference(supertypeDescriptor)
supertypesRefs += ReferenceTranslator.translateAsTypeReference(supertypeDescriptor, context())
}
}
return supertypesRefs
@@ -62,6 +62,7 @@ class DeclarationBodyVisitor(
assert(supertypes.size == 1) { "Simple Enum entry must have one supertype" }
val jsEnumEntryCreation = ClassInitializerTranslator
.generateEnumEntryInstanceCreation(context, supertypes[0], enumEntry, enumEntryOrdinal)
context.addDeclarationStatement(JsAstUtils.newVar(enumInstanceName, jsEnumEntryCreation))
val jsEnumEntryFunction = context.createTopLevelAnonymousFunction(descriptor)
jsEnumEntryFunction.body.statements.add(JsReturn(jsEnumEntryCreation))
@@ -69,12 +70,6 @@ class DeclarationBodyVisitor(
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
context.addDeclarationStatement(enumInstanceFunction.makeStmt())
val classRef = context.getInnerReference(descriptor.containingDeclaration)
val enumExtName = context.getNameForDescriptor(descriptor)
val enumExtFq = JsNameRef(enumExtName, classRef)
context.addDeclarationStatement(JsAstUtils.assignment(enumExtFq, enumInstanceFunction.name.makeRef()).makeStmt())
context.addDeclarationStatement(JsAstUtils.newVar(enumInstanceName, jsEnumEntryCreation))
enumInstanceFunction.body.statements.add(JsReturn(enumInstanceName.makeRef()))
}
@@ -92,7 +87,7 @@ class DeclarationBodyVisitor(
}
override fun addClass(descriptor: ClassDescriptor) {
//context.export(descriptor)
context.export(descriptor)
}
override fun addFunction(descriptor: FunctionDescriptor, expression: JsExpression) {
@@ -518,9 +518,9 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
translateClassOrObject(expression.getObjectDeclaration(), descriptor, context);
translateClassOrObject(expression.getObjectDeclaration(), descriptor, context);
JsExpression constructor = context.getInnerReference(descriptor);
JsExpression constructor = ReferenceTranslator.translateAsTypeReference(descriptor, context);
List<DeclarationDescriptor> closure = context.getClassOrConstructorClosure(descriptor);
List<JsExpression> closureArgs = new ArrayList<JsExpression>();
if (closure != null) {
@@ -21,7 +21,6 @@ import com.google.dart.compiler.backend.js.ast.metadata.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.js.inline.util.getInnerFunction
import org.jetbrains.kotlin.js.inline.util.refreshLabelNames
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.context.getNameForCapturedDescriptor
import org.jetbrains.kotlin.js.translate.context.hasCapturedExceptContaining
@@ -73,12 +72,14 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
if (!isRecursive) {
lambda.name = null
}
lambdaCreator.name.staticRef = lambdaCreator
return lambdaCreator.withCapturedParameters(functionContext, invokingContext)
}
lambda.isLocal = true
context().addDeclarationStatement(lambda.makeStmt())
lambda.name.staticRef = lambda
return lambda.name.makeRef().apply { sideEffects = SideEffectKind.PURE }
}
@@ -92,10 +93,7 @@ class LiteralFunctionTranslator(context: TranslationContext) : AbstractTranslato
}
}
fun JsFunction.withCapturedParameters(
context: TranslationContext,
invokingContext: TranslationContext
): JsExpression {
fun JsFunction.withCapturedParameters(context: TranslationContext, invokingContext: TranslationContext): JsExpression {
context.addDeclarationStatement(makeStmt())
val ref = name.makeRef().apply { sideEffects = SideEffectKind.PURE }
val invocation = JsInvocation(ref).apply { sideEffects = SideEffectKind.PURE }
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.TopLevelFIF;
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.lexer.KtTokens;
@@ -169,7 +170,7 @@ public final class PatternTranslator extends AbstractTranslator {
ClassDescriptor referencedClass = DescriptorUtils.getClassDescriptorForType(type);
JsNameRef typeName = context().getInnerReference(referencedClass);
JsExpression typeName = ReferenceTranslator.translateAsTypeReference(referencedClass, context());
return referencedClass.getKind() != ClassKind.OBJECT ? namer().isInstanceOf(typeName) : namer().isInstanceOfObject(typeName);
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.basic
import com.google.dart.compiler.backend.js.ast.JsExpression
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -43,7 +44,7 @@ class FqnCallIntrinsic(
JsAstUtils.replaceRootReference(context.getQualifiedReference(fqn), Namer.kotlinObject())
}
else {
context.getInnerReference(descriptors.first())
ReferenceTranslator.translateAsValueReference(descriptors.first(), context)
}
}
}
@@ -63,7 +63,7 @@ object CallableReferenceTranslator {
isMember(descriptor) ->
translateForMemberFunction(descriptor, context)
else ->
ReferenceTranslator.translateAsFQReference(descriptor, context)
ReferenceTranslator.translateAsValueReference(descriptor, context)
}
}
@@ -108,14 +108,14 @@ object CallableReferenceTranslator {
}
private fun translateForExtensionProperty(descriptor: PropertyDescriptor, context: TranslationContext): JsExpression {
val jsGetterNameRef = context.getInnerReference(descriptor.getter!!)
val jsGetterNameRef = ReferenceTranslator.translateAsValueReference(descriptor.getter!!, context)
val propertyName = descriptor.name
val jsPropertyNameAsString = context.program().getStringLiteral(propertyName.asString())
val argumentList = ArrayList<JsExpression>(3)
argumentList.add(jsPropertyNameAsString)
argumentList.add(jsGetterNameRef)
if (descriptor.isVar) {
val jsSetterNameRef = context.getInnerReference(descriptor.setter!!)
val jsSetterNameRef = ReferenceTranslator.translateAsValueReference(descriptor.setter!!, context)
argumentList.add(jsSetterNameRef)
}
return if (AnnotationsUtils.isNativeObject(descriptor))
@@ -125,7 +125,7 @@ object CallableReferenceTranslator {
}
private fun translateForConstructor(descriptor: FunctionDescriptor, context: TranslationContext): JsExpression {
val jsFunctionRef = ReferenceTranslator.translateAsFQReference(descriptor, context)
val jsFunctionRef = ReferenceTranslator.translateAsValueReference(descriptor, context)
return JsInvocation(context.namer().callableRefForConstructorReference(), jsFunctionRef)
}
@@ -133,7 +133,7 @@ object CallableReferenceTranslator {
val receiverParameterDescriptor = descriptor.extensionReceiverParameter ?:
error("receiverParameter for extension should not be null")
val jsFunctionRef = ReferenceTranslator.translateAsFQReference(descriptor, context)
val jsFunctionRef = ReferenceTranslator.translateAsValueReference(descriptor, context)
if (descriptor.visibility == Visibilities.LOCAL) {
return JsInvocation(context.namer().callableRefForLocalExtensionFunctionReference(), jsFunctionRef)
}
@@ -159,12 +159,7 @@ object CallableReferenceTranslator {
classDescriptor: ClassDescriptor,
context: TranslationContext
): JsExpression {
val jsClassNameRef = if (AnnotationsUtils.isNativeObject(classDescriptor)) {
context.getQualifiedReference(classDescriptor)
}
else {
context.getInnerReference(classDescriptor)
}
val jsClassNameRef = ReferenceTranslator.translateAsTypeReference(classDescriptor, context)
val funName = context.getNameForDescriptor(descriptor)
val funNameAsString = context.program().getStringLiteral(funName.toString())
return JsInvocation(context.namer().callableRefForMemberFunctionReference(), jsClassNameRef, funNameAsString)
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.psi.KtSimpleNameExpression;
import static org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator.translateAsLocalNameReference;
import static org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator.translateAsValueReference;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
public final class ReferenceAccessTranslator extends AbstractTranslator implements AccessTranslator {
@@ -42,7 +42,7 @@ public final class ReferenceAccessTranslator extends AbstractTranslator implemen
private ReferenceAccessTranslator(@NotNull DeclarationDescriptor descriptor, @NotNull TranslationContext context) {
super(context);
this.reference = translateAsLocalNameReference(descriptor, context());
this.reference = translateAsValueReference(descriptor, context());
}
@Override
@@ -18,6 +18,11 @@ package org.jetbrains.kotlin.js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsInvocation;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata;
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
@@ -43,52 +48,85 @@ public final class ReferenceTranslator {
}
@NotNull
public static JsExpression translateAsFQReference(@NotNull DeclarationDescriptor referencedDescriptor,
@NotNull TranslationContext context) {
JsExpression alias = context.getAliasForDescriptor(referencedDescriptor);
public static JsExpression translateAsValueReference(@NotNull DeclarationDescriptor descriptor, @NotNull TranslationContext context) {
JsExpression alias = context.getAliasForDescriptor(descriptor);
if (alias != null) return alias;
if (isLocalVarOrFunction(referencedDescriptor) ||
AnnotationsUtils.isNativeObject(referencedDescriptor) ||
AnnotationsUtils.isLibraryObject(referencedDescriptor)
) {
return context.getQualifiedReference(referencedDescriptor);
if (shouldTranslateAsFQN(descriptor, context)) {
return context.getQualifiedReference(descriptor);
}
return context.getInnerReference(referencedDescriptor);
}
private static boolean isLocalVarOrFunction(DeclarationDescriptor descriptor) {
return descriptor.getContainingDeclaration() instanceof FunctionDescriptor && !(descriptor instanceof ClassDescriptor);
}
@NotNull
public static JsExpression translateAsLocalNameReference(@NotNull DeclarationDescriptor descriptor,
@NotNull TranslationContext context) {
if (descriptor instanceof FunctionDescriptor || descriptor instanceof VariableDescriptor) {
JsExpression alias = context.getAliasForDescriptor(descriptor);
if (alias != null) {
return alias;
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor property = (PropertyDescriptor) descriptor;
if (context.isFromCurrentModule(property)) {
return context.getInnerReference(property);
}
else {
JsExpression qualifier = context.getInnerReference(property.getContainingDeclaration());
JsName name = context.getNameForDescriptor(property);
return new JsNameRef(name, qualifier);
}
}
if (DescriptorUtils.isObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor)) {
if (AnnotationsUtils.isNativeObject(descriptor)) {
return context.getQualifiedReference(descriptor);
}
else if (!context.isFromCurrentModule(descriptor)) {
DeclarationDescriptor container = descriptor.getContainingDeclaration();
assert container != null : "Object must have containing declaration: " + descriptor;
JsExpression qualifier = context.getInnerReference(container);
return JsAstUtils.pureFqn(context.getNameForDescriptor(descriptor), qualifier);
return getLazyReferenceToObject((ClassDescriptor) descriptor, context);
}
else {
JsExpression functionRef = JsAstUtils.pureFqn(context.getNameForObjectInstance((ClassDescriptor) descriptor), null);
return new JsInvocation(functionRef);
}
}
return context.getInnerReference(descriptor);
}
@NotNull
public static JsExpression translateAsTypeReference(@NotNull ClassDescriptor descriptor, @NotNull TranslationContext context) {
if (AnnotationsUtils.isNativeObject(descriptor)) {
return context.getQualifiedReference(descriptor);
}
if (!shouldTranslateAsFQN(descriptor, context)) {
if (DescriptorUtils.isObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor)) {
if (!context.isFromCurrentModule(descriptor)) {
return getLazyReferenceToObject(descriptor, context);
}
}
return context.getInnerReference(descriptor);
}
JsExpression reference = context.getQualifiedReference(descriptor);
if (DescriptorUtils.isObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor)) {
JsNameRef getPrototypeRef = JsAstUtils.pureFqn("getPrototypeOf", JsAstUtils.pureFqn("Object", null));
JsInvocation getPrototypeInvocation = new JsInvocation(getPrototypeRef, reference);
MetadataProperties.setSideEffects(getPrototypeInvocation, SideEffectKind.PURE);
reference = JsAstUtils.pureFqn("constructor", getPrototypeInvocation);
}
return reference;
}
@NotNull
private static JsExpression getLazyReferenceToObject(@NotNull ClassDescriptor descriptor, @NotNull TranslationContext context) {
DeclarationDescriptor container = descriptor.getContainingDeclaration();
JsExpression qualifier = context.getInnerReference(container);
return JsAstUtils.pureFqn(context.getNameForDescriptor(descriptor), qualifier);
}
private static boolean shouldTranslateAsFQN(@NotNull DeclarationDescriptor descriptor, @NotNull TranslationContext context) {
return isLocalVarOrFunction(descriptor) ||
AnnotationsUtils.isNativeObject(descriptor) ||
AnnotationsUtils.isLibraryObject(descriptor) ||
context.isPublicInlineFunction();
}
private static boolean isLocalVarOrFunction(DeclarationDescriptor descriptor) {
return descriptor.getContainingDeclaration() instanceof FunctionDescriptor && !(descriptor instanceof ClassDescriptor);
}
@NotNull
public static AccessTranslator getAccessTranslator(@NotNull KtSimpleNameExpression referenceExpression,
@NotNull TranslationContext context) {
@@ -58,7 +58,7 @@ public final class JSTestGenerator {
private static void generateCodeForTestMethod(@NotNull TranslationContext context,
@NotNull FunctionDescriptor functionDescriptor,
@NotNull ClassDescriptor classDescriptor, @NotNull JSTester tester) {
JsExpression expression = ReferenceTranslator.translateAsFQReference(classDescriptor, context);
JsExpression expression = ReferenceTranslator.translateAsValueReference(classDescriptor, context);
JsNew testClass = new JsNew(expression);
JsExpression functionToTestCall = CallTranslator.INSTANCE.buildCall(context, functionDescriptor,
Collections.<JsExpression>emptyList(), testClass);
@@ -52,13 +52,13 @@ fun setInlineCallMetadata(
"Expected descriptor of callable, that should be inlined, but got: $descriptor"
}
val name = context.aliasedName(descriptor)
val candidateNames = setOf(context.aliasedName(descriptor), context.getInnerNameForDescriptor(descriptor))
val visitor = object : RecursiveJsVisitor() {
override fun visitInvocation(invocation: JsInvocation) {
super.visitInvocation(invocation)
if (name == invocation.name) {
if (invocation.name in candidateNames) {
invocation.descriptor = descriptor
invocation.inlineStrategy = InlineStrategy.IN_PLACE
invocation.psiElement = psiElement
@@ -21,6 +21,7 @@ import com.intellij.util.SmartList
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.simpleReturnFunction
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType
@@ -78,27 +79,21 @@ fun <T, S> List<T>.splitToRanges(classifier: (T) -> S): List<Pair<List<T>, S>> {
return result
}
fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsNameRef {
val referenceToJsClass: JsNameRef
fun getReferenceToJsClass(type: KotlinType, context: TranslationContext): JsExpression {
val classifierDescriptor = type.constructor.declarationDescriptor
if (classifierDescriptor is ClassDescriptor) {
val reference = context.getInnerReference(classifierDescriptor)
if (classifierDescriptor.kind == ClassKind.OBJECT) {
referenceToJsClass = JsAstUtils.pureFqn("constructor", JsInvocation(JsNameRef("getPrototypeOf", JsNameRef("Object")), reference))
val referenceToJsClass: JsExpression = when (classifierDescriptor) {
is ClassDescriptor -> {
ReferenceTranslator.translateAsTypeReference(classifierDescriptor, context)
}
else {
referenceToJsClass = reference
}
}
else if (classifierDescriptor is TypeParameterDescriptor) {
assert(classifierDescriptor.isReified)
is TypeParameterDescriptor -> {
assert(classifierDescriptor.isReified)
referenceToJsClass = context.getNameForDescriptor(classifierDescriptor).makeRef()
}
else {
throw IllegalStateException("Can't get reference for $type")
context.getNameForDescriptor(classifierDescriptor).makeRef()
}
else -> {
throw IllegalStateException("Can't get reference for $type")
}
}
return referenceToJsClass
@@ -5,13 +5,13 @@ package foo
@native
const val ROOT = "Kotlin.modules.JS_TESTS"
@native
const val PATH_TO_F_CREATOR = "foo.B.far\$f"
const val PATH_TO_F_CREATOR = "B\$far\$lambda"
@native
const val PATH_TO_G_CREATOR = "foo.B.gar\$f"
const val PATH_TO_G_CREATOR = "B\$gar\$lambda"
@native("$ROOT.$PATH_TO_F_CREATOR")
@native("$PATH_TO_F_CREATOR")
val F_CREATOR: Any = noImpl
@native("$ROOT.$PATH_TO_G_CREATOR")
@native("$PATH_TO_G_CREATOR")
val G_CREATOR: Any = noImpl
@@ -38,7 +38,7 @@ fun box(): String {
assertEquals("B::boo", g())
val fs = F_CREATOR.toString()
val gs = G_CREATOR.toString().replaceAll("boo", "foo")
val gs = G_CREATOR.toString().replaceAll("boo", "foo").replaceAll("gar", "far")
assertEquals(gs, fs)
+2 -2
View File
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: multiplyInline_0
// CHECK_NOT_CALLED: runNoinline_0
// CHECK_CONTAINS_NO_CALLS: multiplyInline
// CHECK_NOT_CALLED: runNoinline
internal inline fun multiply(a: Int, b: Int) = a * b
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
// A copy of stdlib run function.
// Copied to not to depend on run implementation.
@@ -1,6 +1,6 @@
package foo
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiply_0 function=multiply_0$f
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiply function=multiply$lambda
internal class A(val a: Int)
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: squareMultipliedByTwo_0
// CHECK_CONTAINS_NO_CALLS: squareMultipliedByTwo
internal inline fun inline1(a: Int): Int {
return a
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: squareMultipliedByTwo_0
// CHECK_CONTAINS_NO_CALLS: squareMultipliedByTwo
internal inline fun inline1(a: Int): Int {
return a
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: identity_0
// CHECK_CONTAINS_NO_CALLS: sumNoInline_0
// CHECK_CONTAINS_NO_CALLS: identity
// CHECK_CONTAINS_NO_CALLS: sumNoInline
internal inline fun sum(a: Int, b: Int = 0): Int {
return a + b
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: doNothingNoInline_0
// CHECK_CONTAINS_NO_CALLS: doNothingNoInline
internal inline fun <T> doNothing1(a: T): T {
return a
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: doNothingInt_0
// CHECK_CONTAINS_NO_CALLS: doNothingStr_0
// CHECK_CONTAINS_NO_CALLS: doNothingInt
// CHECK_CONTAINS_NO_CALLS: doNothingStr
internal inline fun <T> doNothing(a: T): T {
return a
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: multiplyNoInline_0
// CHECK_CONTAINS_NO_CALLS: multiplyNoInline
internal inline fun multiply(a: Int, b: Int): Int {
return a * b
+3 -3
View File
@@ -1,8 +1,8 @@
package foo
// CHECK_CONTAINS_NO_CALLS: doNothing1_0
// CHECK_CONTAINS_NO_CALLS: doNothing2_0
// CHECK_CONTAINS_NO_CALLS: doNothing3_0
// CHECK_CONTAINS_NO_CALLS: doNothing1
// CHECK_CONTAINS_NO_CALLS: doNothing2
// CHECK_CONTAINS_NO_CALLS: doNothing3
internal class Inline {
public inline fun <T> identity1 (x: T): T {
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: sumEven_0
// CHECK_CONTAINS_NO_CALLS: sumEven
internal inline fun filteredReduce(a: Array<Int>, predicate: (Int) -> Boolean, reduceFun: (Int, Int) -> Int): Int {
var result = 0
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: maxBySquare_0
// CHECK_CONTAINS_NO_CALLS: maxBySquare
internal data class Result(var value: Int = 0, var invocationCount: Int = 0)
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: add_0
// CHECK_CONTAINS_NO_CALLS: add
internal data class IntPair(public var fst: Int, public var snd: Int) {
inline public fun getFst(): Int { return fst }
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: factAbsNoInline1_0
// CHECK_CONTAINS_NO_CALLS: factAbsNoInline1
internal class State(value: Int) {
public var value: Int = value
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal inline fun sum(x: Int, y: Int): Int = js("x + y")
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal inline fun sum(x: Int, y: Int): Int = js("var a = x; a + y")
+3 -3
View File
@@ -1,8 +1,8 @@
package foo
// CHECK_CALLED_IN_SCOPE: scope=multiplyBy2_0 function=multiplyBy2_0$f
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2_0 function=multiplyBy2_0$f_0
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2_0 function=run
// CHECK_CALLED_IN_SCOPE: scope=multiplyBy2 function=multiplyBy2$lambda
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2 function=multiplyBy2$lambda_0
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2 function=run
internal inline fun <T> runLambdaInLambda(noinline inner: (T) -> T, outer: ((T) -> T, T) -> T, arg: T): T {
return outer(inner, arg)
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: capturedInLambda_0
// CHECK_CONTAINS_NO_CALLS: declaredInLambda_0
// CHECK_CONTAINS_NO_CALLS: capturedInLambda
// CHECK_CONTAINS_NO_CALLS: declaredInLambda
internal data class State(var count: Int = 0)
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: localWithCapture_0
// CHECK_CONTAINS_NO_CALLS: localWithoutCapture_0
// CHECK_CONTAINS_NO_CALLS: localWithCapture
// CHECK_CONTAINS_NO_CALLS: localWithoutCapture
internal inline fun repeatAction(times: Int, action: () -> Unit) {
for (i in 1..times) {
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: add_0
// CHECK_CONTAINS_NO_CALLS: add
internal data class State(var count: Int = 0)
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: localWithCapture_0
// CHECK_CONTAINS_NO_CALLS: localWithoutCapture_0
// CHECK_CONTAINS_NO_CALLS: localWithCapture
// CHECK_CONTAINS_NO_CALLS: localWithoutCapture
internal inline fun repeatAction(times: Int, action: () -> Unit) {
for (i in 1..times) {
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: add_0
// CHECK_CONTAINS_NO_CALLS: add
internal inline fun run(action: () -> Int): Int {
return action()
@@ -1,11 +1,11 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test1_0
// CHECK_CONTAINS_NO_CALLS: test2_0
// CHECK_CONTAINS_NO_CALLS: test3_0
// CHECK_CONTAINS_NO_CALLS: test1
// CHECK_CONTAINS_NO_CALLS: test2
// CHECK_CONTAINS_NO_CALLS: test3
// CHECK_CONTAINS_NO_CALLS: test4_buocd8$
// CHECK_CONTAINS_NO_CALLS: test5_0
// CHECK_HAS_INLINE_METADATA: apply_hiyix$
// CHECK_CONTAINS_NO_CALLS: test5
// CHECK_HAS_INLINE_METADATA: apply
// CHECK_HAS_INLINE_METADATA: applyL_hiyix$
// CHECK_HAS_INLINE_METADATA: applyM_hiyix$
// CHECK_HAS_NO_INLINE_METADATA: applyN_hiyix$
+2 -2
View File
@@ -1,7 +1,7 @@
package foo
// CHECK_CALLED_IN_SCOPE: scope=multiplyBy2_0 function=multiplyBy2_0$f
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2_0 function=run
// CHECK_CALLED_IN_SCOPE: scope=multiplyBy2 function=multiplyBy2$lambda
// CHECK_NOT_CALLED_IN_SCOPE: scope=multiplyBy2 function=run
internal inline fun <T> run(noinline func: (T) -> T, arg: T): T {
return func(arg)
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: sum_0
// CHECK_CONTAINS_NO_CALLS: sum
inline fun <T : Any, R> T.doLet(f: (T) -> R): R = f(this)
+3 -3
View File
@@ -1,9 +1,9 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test1_0
// CHECK_CONTAINS_NO_CALLS: test2_0
// CHECK_CONTAINS_NO_CALLS: test3_0 except=slice
// CHECK_CONTAINS_NO_CALLS: test1
// CHECK_CONTAINS_NO_CALLS: test2
// CHECK_CONTAINS_NO_CALLS: test3 except=slice
internal inline fun concat(vararg strings: String): String {
var result = ""
+1 -1
View File
@@ -8,7 +8,7 @@ package foo
import test.*
// CHECK_CONTAINS_NO_CALLS: testClassObject_0
// CHECK_CONTAINS_NO_CALLS: testClassObject
internal fun testFinalInline(): String {
return Z().finalInline({"final"})
@@ -17,7 +17,7 @@ public fun log(s: String): String {
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(s: String): String = log(s + ";")
@@ -12,7 +12,7 @@ public fun <T, R> apply(x: T, fn: (T)->R): R =
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun multiplyBy2(x: Int): Int = x * 2
@@ -9,7 +9,7 @@ public fun sum(x: Int, y: Int): Int =
// MODULE: main(lib)
// FILE: main.kt
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(x: Int, y: Int): Int = utils.sum(x, y)
@@ -13,7 +13,7 @@ public fun <T, R> apply(x: T, fn: T.()->R): R =
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal class A(val n: Int)
+1 -1
View File
@@ -13,7 +13,7 @@ public fun <T, R> apply(x: T, fn: (T)->R): R =
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(x: Int): Int = apply(x) { it * 2 }
@@ -13,7 +13,7 @@ public fun <T, R> apply(x: T, fn: (T)->R): R =
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(x: Int, y: Int): Int = apply(x) { it + y }
@@ -15,7 +15,7 @@ public fun <T, R> apply(x: T, fn: (T)->R): R {
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(x: Int, y: Int): Int = apply(x) { it + 1 } * y
+1 -1
View File
@@ -14,7 +14,7 @@ public class A(public val x: Int) {
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(a: A, y: Int): Int = a.plus(y)
+1 -1
View File
@@ -13,7 +13,7 @@ public fun sum(x: Int, y: Int): Int =
import utils.*
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(x: Int, y: Int): Int = sum(x, y)
@@ -1,8 +1,8 @@
package foo
// CHECK_NOT_CALLED: f1_0
// CHECK_NOT_CALLED: f2_0
// CHECK_BREAKS_COUNT: function=test_0 count=3
// CHECK_NOT_CALLED: f1
// CHECK_NOT_CALLED: f2
// CHECK_BREAKS_COUNT: function=test count=3
internal var even = arrayListOf<Int>()
internal var odd = arrayListOf<Int>()
@@ -1,6 +1,6 @@
package foo
// CHECK_VARS_COUNT: function=test_za3lpa$ count=2
// CHECK_VARS_COUNT: function=test count=2
inline fun if1(f: (Int) -> Int, a: Int, b: Int, c: Int): Int {
val result = f(a)
@@ -1,9 +1,9 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test1_0
// CHECK_CONTAINS_NO_CALLS: test2_0
// CHECK_VARS_COUNT: function=test1_0 count=0
// CHECK_VARS_COUNT: function=test2_0 count=1
// CHECK_CONTAINS_NO_CALLS: test1
// CHECK_CONTAINS_NO_CALLS: test2
// CHECK_VARS_COUNT: function=test1 count=0
// CHECK_VARS_COUNT: function=test2 count=1
var log = ""
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_VARS_COUNT: function=test_0 count=0
// CHECK_CONTAINS_NO_CALLS: test except=SumHolder_getInstance
// CHECK_VARS_COUNT: function=test count=1
object SumHolder {
var sum = 0
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_VARS_COUNT: function=test_0 count=0
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_VARS_COUNT: function=test count=0
internal inline fun sign(x: Int): Int {
if (x < 0) return -1
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_VARS_COUNT: function=test_0 count=0
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_VARS_COUNT: function=test count=0
// A copy of stdlib run function.
// Copied to not to depend on run implementation.
@@ -1,8 +1,8 @@
package foo
// CHECK_VARS_COUNT: function=test1_za3lpa$ count=0
// CHECK_VARS_COUNT: function=test2_za3lpa$ count=1
// CHECK_VARS_COUNT: function=test3_za3lpa$ count=0
// CHECK_VARS_COUNT: function=test1 count=0
// CHECK_VARS_COUNT: function=test2 count=1
// CHECK_VARS_COUNT: function=test3 count=0
inline fun a(x: Int) = b(x)
+2 -2
View File
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_VARS_COUNT: function=test_0 count=0
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_VARS_COUNT: function=test count=0
internal class A(val x: Int) {
inline fun f(): Int = x
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_VARS_COUNT: function=test_0 count=1
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_VARS_COUNT: function=test count=1
internal inline fun sum(x: Int, y: Int): Int {
if (x == 0 || y == 0) return 0
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_VARS_COUNT: function=test_0 count=1
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_VARS_COUNT: function=test count=1
internal inline fun sum(x: Int, y: Int): Int {
if (x == 0 || y == 0) return 0
@@ -1,7 +1,7 @@
package foo
// CHECK_NOT_CALLED_IN_SCOPE: scope=test_0 function=even_0
// CHECK_NOT_CALLED_IN_SCOPE: scope=test_0 function=filter_azvtw4$
// CHECK_NOT_CALLED_IN_SCOPE: scope=test function=even
// CHECK_NOT_CALLED_IN_SCOPE: scope=test function=filter_azvtw4$
internal fun even(x: Int) = x % 2 == 0
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(a: Int, b: Int): Int {
var c = 0
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(a: Int, b: Int): Int {
var res = 0
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal fun test(x: Int, y: Int): Int =
with (x + x) {
+1 -1
View File
@@ -1,6 +1,6 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_CONTAINS_NO_CALLS: test
internal var counter = 0
@@ -1,7 +1,7 @@
package foo
// CHECK_CONTAINS_NO_CALLS: testImplicitThis_0
// CHECK_CONTAINS_NO_CALLS: testExplicitThis_0
// CHECK_CONTAINS_NO_CALLS: testImplicitThis
// CHECK_CONTAINS_NO_CALLS: testExplicitThis
internal class A(var value: Int)
@@ -1,9 +1,9 @@
package foo
// CHECK_CONTAINS_NO_CALLS: test_0
// CHECK_LABELS_COUNT: function=test_0 name=loop count=1
// CHECK_LABELS_COUNT: function=test_0 name=loop_0 count=1
// CHECK_LABELS_COUNT: function=test_0 name=loop_1 count=1
// CHECK_CONTAINS_NO_CALLS: test
// CHECK_LABELS_COUNT: function=test name=loop count=1
// CHECK_LABELS_COUNT: function=test name=loop_0 count=1
// CHECK_LABELS_COUNT: function=test name=loop_1 count=1
class State() {
public var value: Int = 0
@@ -1,8 +1,8 @@
package foo
// CHECK_LABELS_COUNT: function=test_0 name=loop count=1
// CHECK_LABELS_COUNT: function=test_0 name=loop_0 count=1
// CHECK_LABELS_COUNT: function=test_0 name=loop_1 count=1
// CHECK_LABELS_COUNT: function=test name=loop count=1
// CHECK_LABELS_COUNT: function=test name=loop_0 count=1
// CHECK_LABELS_COUNT: function=test name=loop_1 count=1
class State() {
public var value: Int = 0
-45
View File
@@ -1,45 +0,0 @@
NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
dataClass / param
dataClass / val
dataClass / var
delegated / fun
delegated / funParam
delegated / label
delegated / val
delegated / var
enum / entry
enum / fun
enum / funParam
enum / label
enum / val
enum / var
insideClass / fun
insideClass / funParam
insideClass / label
insideClass / val
insideClass / var
insideClassObject / fun
insideClassObject / funParam
insideClassObject / label
insideClassObject / val
insideClassObject / var
insideObject / fun
insideObject / funParam
insideObject / label
insideObject / val
insideObject / var
local / catch
local / fun
local / funParam
local / label
local / val
local / var
toplevel / class
toplevel / enum
toplevel / fun
toplevel / funParam
toplevel / interface
toplevel / label
toplevel / object
toplevel / val
toplevel / var
@@ -1,22 +0,0 @@
NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
break
class
continue
do
else
false
for
if
in
interface
null
package
return
super
this
throw
true
try
typeof
var
while
@@ -1,32 +0,0 @@
NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
Infinity
Kotlin
NaN
arguments
await
case
catch
const
debugger
default
delete
enum
eval
export
extends
finally
function
implements
import
instanceof
let
new
private
protected
public
static
switch
undefined
void
with
yield
-24
View File
@@ -1,24 +0,0 @@
package foo
import kotlin.text.Regex
fun testRenamed(case: String, f: () -> Unit) = test(case, true, f)
fun testNotRenamed(case: String, f: () -> Unit) = test(case, false, f)
fun test(keyword: String, expectedRenamed: Boolean, f: Any) {
val fs = f.toString().replace("while (false)", "")
val matches = Regex("[\\w$]*$keyword[\\w_$]*").matchAll(fs).map { it.value }.toList()
assertNotEquals(0, matches.size, "matches is empty for fs = $fs")
val actual = matches.last()
assertTrue(actual.contains(keyword), "'$keyword' not found in '$matches' from '$fs'")
if (expectedRenamed) {
assertNotEquals(keyword, actual, "fs = $fs")
}
else {
assertEquals(keyword, actual, "fs = $fs")
}
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(val `typeof`: String) {
init {
testNotRenamed("typeof", { `typeof` })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(val `var`: String) {
init {
testNotRenamed("var", { `var` })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(val with: String) {
init {
testNotRenamed("with", { with })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(val yield: String) {
init {
testNotRenamed("yield", { yield })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(var `break`: String) {
init {
testNotRenamed("break", { `break` })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(var Infinity: String) {
init {
testNotRenamed("Infinity", { Infinity })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(var Kotlin: String) {
init {
testNotRenamed("Kotlin", { Kotlin })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,15 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
data class DataClass(var `while`: String) {
init {
testNotRenamed("while", { `while` })
}
}
fun box(): String {
DataClass("123")
return "OK"
}
@@ -1,23 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun debugger()
}
class TraitImpl : Trait {
override fun debugger() { debugger() }
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
testNotRenamed("debugger", { debugger() })
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}
@@ -1,23 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun default()
}
class TraitImpl : Trait {
override fun default() { default() }
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
testNotRenamed("default", { default() })
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}
@@ -1,23 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun `if`()
}
class TraitImpl : Trait {
override fun `if`() { `if`() }
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
testNotRenamed("if", { `if`() })
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}
@@ -1,23 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun `in`()
}
class TraitImpl : Trait {
override fun `in`() { `in`() }
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
testNotRenamed("in", { `in`() })
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}
@@ -1,26 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun foo(delete: String)
}
class TraitImpl : Trait {
override fun foo(delete: String) {
assertEquals("123", delete)
testRenamed("delete", { delete })
}
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
foo("123")
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}
@@ -1,26 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun foo(enum: String)
}
class TraitImpl : Trait {
override fun foo(enum: String) {
assertEquals("123", enum)
testRenamed("enum", { enum })
}
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
foo("123")
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}
@@ -1,26 +0,0 @@
package foo
// NOTE THIS FILE IS AUTO-GENERATED by the generateTestDataForReservedWords.kt. DO NOT EDIT!
interface Trait {
fun foo(`interface`: String)
}
class TraitImpl : Trait {
override fun foo(`interface`: String) {
assertEquals("123", `interface`)
testRenamed("interface", { `interface` })
}
}
class TestDelegate : Trait by TraitImpl() {
fun test() {
foo("123")
}
}
fun box(): String {
TestDelegate().test()
return "OK"
}

Some files were not shown because too many files have changed in this diff Show More