Fixes for cases where unexpected declaration descriptor hierarchy caused invalid scoping structure in js backend.

Minor refactorings.
This commit is contained in:
Pavel V. Talanov
2012-03-15 19:13:40 +04:00
parent e4a658fbeb
commit 090fd1b7f6
17 changed files with 186 additions and 139 deletions
@@ -93,7 +93,23 @@ public final class MiscTest extends AbstractExpressionTest {
checkFooBoxIsTrue("funInConstructor.kt"); checkFooBoxIsTrue("funInConstructor.kt");
} }
public void testFunInConstructorBlock() throws Exception {
checkFooBoxIsTrue("funInConstructorBlock.kt");
}
public void testPropertyAsFunCalledOnConstructor() throws Exception { public void testPropertyAsFunCalledOnConstructor() throws Exception {
checkFooBoxIsTrue("propertyAsFunCalledOnConstructor.kt"); checkFooBoxIsTrue("propertyAsFunCalledOnConstructor.kt");
} }
public void testNamespacePropertyCalledAsFun() throws Exception {
checkFooBoxIsTrue("namespacePropertyCalledAsFun.kt");
}
public void testExtensionLiteralCreatedAtNamespaceLevel() throws Exception {
checkFooBoxIsTrue("extensionLiteralCreatedAtNamespaceLevel.kt");
}
public void testTemporaryVariableCreatedInNamespaceInitializer() throws Exception {
checkFooBoxIsTrue("temporaryVariableCreatedInNamespaceInitializer.kt");
}
} }
@@ -26,54 +26,48 @@ public class DynamicContext {
@NotNull @NotNull
public static DynamicContext rootContext(@NotNull NamingScope rootScope, @NotNull JsBlock globalBlock) { public static DynamicContext rootContext(@NotNull NamingScope rootScope, @NotNull JsBlock globalBlock) {
return new DynamicContext(rootScope, rootScope, globalBlock); return new DynamicContext(rootScope, globalBlock);
} }
@NotNull @NotNull
public static DynamicContext contextWithScope(@NotNull NamingScope scope) { public static DynamicContext newContext(@NotNull NamingScope scope, @NotNull JsBlock block) {
return new DynamicContext(scope, scope, new JsBlock()); return new DynamicContext(scope, block);
} }
//TODO: current/block scope logic unclear. is it necessary?
@NotNull @NotNull
private final NamingScope currentScope; private final NamingScope currentScope;
@NotNull
private final NamingScope blockScope;
@NotNull @NotNull
private final JsBlock currentBlock; private final JsBlock currentBlock;
private DynamicContext(@NotNull NamingScope scope, @NotNull NamingScope blockScope, @NotNull JsBlock block) { private DynamicContext(@NotNull NamingScope scope, @NotNull JsBlock block) {
this.currentScope = scope; this.currentScope = scope;
this.currentBlock = block; this.currentBlock = block;
this.blockScope = blockScope;
}
@NotNull
public DynamicContext innerScope(@NotNull JsScope scope) {
return new DynamicContext(currentScope.innerScope(scope), blockScope, currentBlock);
} }
@NotNull @NotNull
public DynamicContext innerBlock(@NotNull JsBlock block) { public DynamicContext innerBlock(@NotNull JsBlock block) {
return new DynamicContext(currentScope, currentScope, block); return new DynamicContext(currentScope, block);
} }
@NotNull @NotNull
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) { public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) {
JsName temporaryName = blockScope.declareTemporary(); JsName temporaryName = currentScope.declareTemporary();
JsVars temporaryDeclaration = newVar(temporaryName, /*no init expression in var statement*/ null); JsVars temporaryDeclaration = newVar(temporaryName, /*no init expression in var statement*/ null);
addVarDeclaration(jsBlock(), temporaryDeclaration); addVarDeclaration(jsBlock(), temporaryDeclaration);
return new TemporaryVariable(temporaryName, initExpression); return new TemporaryVariable(temporaryName, initExpression);
} }
@NotNull @NotNull
public JsScope jsScope() { public JsScope jsScope() {
return currentScope.jsScope(); return currentScope.jsScope();
} }
@NotNull
public NamingScope getScope() {
return currentScope;
}
@NotNull @NotNull
public JsBlock jsBlock() { public JsBlock jsBlock() {
return currentBlock; return currentBlock;
@@ -27,6 +27,7 @@ import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule; import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import org.jetbrains.k2js.translate.utils.AnnotationsUtils; import org.jetbrains.k2js.translate.utils.AnnotationsUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.PredefinedAnnotation; import org.jetbrains.k2js.translate.utils.PredefinedAnnotation;
import java.util.Map; import java.util.Map;
@@ -84,7 +85,6 @@ public final class StaticContext {
private final Generator<JsNameRef> qualifiers = new QualifierGenerator(); private final Generator<JsNameRef> qualifiers = new QualifierGenerator();
@NotNull @NotNull
private final Generator<Boolean> qualifierIsNull = new QualifierIsNullGenerator(); private final Generator<Boolean> qualifierIsNull = new QualifierIsNullGenerator();
@NotNull @NotNull
private final Map<NamingScope, JsFunction> scopeToFunction = Maps.newHashMap(); private final Map<NamingScope, JsFunction> scopeToFunction = Maps.newHashMap();
@@ -135,7 +135,7 @@ public final class StaticContext {
@NotNull @NotNull
public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { public NamingScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
NamingScope namingScope = scopes.get(descriptor); NamingScope namingScope = scopes.get(descriptor.getOriginal());
assert namingScope != null : "Must have a scope for descriptor"; assert namingScope != null : "Must have a scope for descriptor";
return namingScope; return namingScope;
} }
@@ -337,8 +337,9 @@ public final class StaticContext {
return null; return null;
} }
NamingScope enclosingScope = getEnclosingScope(descriptor); NamingScope enclosingScope = getEnclosingScope(descriptor);
JsFunction correspondingFunction = new JsFunction(enclosingScope.jsScope()); JsFunction correspondingFunction = JsAstUtils.createFunctionWithEmptyBody(enclosingScope.jsScope());
NamingScope newScope = enclosingScope.innerScope(correspondingFunction.getScope()); NamingScope newScope = enclosingScope.innerScope(correspondingFunction.getScope());
assert (!scopeToFunction.containsKey(newScope)) : "Scope to function value overriden for " + descriptor;
scopeToFunction.put(newScope, correspondingFunction); scopeToFunction.put(newScope, correspondingFunction);
return newScope; return newScope;
} }
@@ -53,14 +53,8 @@ public final class TranslationContext {
} }
@NotNull @NotNull
public TranslationContext contextWithScope(@NotNull NamingScope newScope) { public TranslationContext contextWithScope(@NotNull NamingScope newScope, @NotNull JsBlock block) {
return new TranslationContext(staticContext, DynamicContext.contextWithScope(newScope)); return new TranslationContext(staticContext, DynamicContext.newContext(newScope, block));
}
// Note: Should be used ONLY if scope has no corresponding descriptor
@NotNull
public TranslationContext innerJsScope(@NotNull JsScope enclosingScope) {
return new TranslationContext(staticContext, dynamicContext.innerScope(enclosingScope));
} }
@NotNull @NotNull
@@ -70,7 +64,23 @@ public final class TranslationContext {
@NotNull @NotNull
public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) { public TranslationContext newDeclaration(@NotNull DeclarationDescriptor descriptor) {
return contextWithScope(getScopeForDescriptor(descriptor)); return contextWithScope(getScopeForDescriptor(descriptor), getBlockForDescriptor(descriptor));
}
//TODO: consider passing a function here
@NotNull
public TranslationContext innerContextWithGivenScopeAndBlock(@NotNull JsScope scope, @NotNull JsBlock block) {
return contextWithScope(dynamicContext.getScope().innerScope(scope), block);
}
@NotNull
public JsBlock getBlockForDescriptor(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof CallableDescriptor) {
return getFunctionObject((CallableDescriptor) descriptor).getBody();
}
else {
return new JsBlock();
}
} }
@NotNull @NotNull
@@ -125,7 +125,7 @@ public final class PropertyTranslator extends AbstractTranslator {
private JsFunction generateDefaultGetterFunction(@NotNull PropertyGetterDescriptor descriptor) { private JsFunction generateDefaultGetterFunction(@NotNull PropertyGetterDescriptor descriptor) {
JsReturn returnExpression = new JsReturn(backingFieldReference(context(), property)); JsReturn returnExpression = new JsReturn(backingFieldReference(context(), property));
JsFunction getterFunction = context().getFunctionObject(descriptor); JsFunction getterFunction = context().getFunctionObject(descriptor);
getterFunction.setBody(convertToBlock(returnExpression)); getterFunction.getBody().getStatements().add(returnExpression);
return getterFunction; return getterFunction;
} }
@@ -144,7 +144,7 @@ public final class PropertyTranslator extends AbstractTranslator {
new JsParameter(propertyAccessContext(propertySetterDescriptor).jsScope().declareTemporary()); new JsParameter(propertyAccessContext(propertySetterDescriptor).jsScope().declareTemporary());
JsStatement assignment = assignmentToBackingField(context(), property, defaultParameter.getName().makeRef()).makeStmt(); JsStatement assignment = assignmentToBackingField(context(), property, defaultParameter.getName().makeRef()).makeStmt();
setParameters(result, defaultParameter); setParameters(result, defaultParameter);
result.setBody(convertToBlock(assignment)); result.getBody().getStatements().add(assignment);
return result; return result;
} }
@@ -52,6 +52,8 @@ import static org.jetbrains.k2js.translate.utils.mutator.LastExpressionMutator.m
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
//TODO: class has convoluted code. REFACTOR before changing
public final class FunctionTranslator extends AbstractTranslator { public final class FunctionTranslator extends AbstractTranslator {
@NotNull @NotNull
@@ -75,10 +77,10 @@ public final class FunctionTranslator extends AbstractTranslator {
private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration, private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
super(context); super(context);
this.functionBody = new JsBlock();
this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration); this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration);
this.functionDeclaration = functionDeclaration; this.functionDeclaration = functionDeclaration;
this.functionObject = createFunctionObject(); this.functionObject = context().getFunctionObject(descriptor);
this.functionBody = functionObject.getBody();
this.functionBodyContext = functionBodyContext().innerBlock(functionBody); this.functionBodyContext = functionBodyContext().innerBlock(functionBody);
} }
@@ -147,7 +149,6 @@ public final class FunctionTranslator extends AbstractTranslator {
private void generateFunctionObject() { private void generateFunctionObject() {
setParameters(functionObject, translateParameters()); setParameters(functionObject, translateParameters());
translateBody(); translateBody();
functionObject.setBody(functionBody);
restoreContext(); restoreContext();
} }
@@ -159,11 +160,6 @@ public final class FunctionTranslator extends AbstractTranslator {
} }
} }
@NotNull
private JsFunction createFunctionObject() {
return context().getFunctionObject(descriptor);
}
private void translateBody() { private void translateBody() {
JetExpression jetBodyExpression = functionDeclaration.getBodyExpression(); JetExpression jetBodyExpression = functionDeclaration.getBodyExpression();
if (jetBodyExpression == null) { if (jetBodyExpression == null) {
@@ -203,12 +199,7 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull @NotNull
private TranslationContext functionBodyContext() { private TranslationContext functionBodyContext() {
if (isLiteral()) { return context().newDeclaration(functionDeclaration);
return context().innerJsScope(functionObject.getScope());
}
else {
return context().newDeclaration(functionDeclaration);
}
} }
@NotNull @NotNull
@@ -100,13 +100,15 @@ public final class Translation {
@NotNull @NotNull
public static JsPropertyInitializer generateClassInitializerMethod(@NotNull JetClassOrObject classDeclaration, public static JsPropertyInitializer generateClassInitializerMethod(@NotNull JetClassOrObject classDeclaration,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new ClassInitializerTranslator(classDeclaration, context)).generateInitializeMethod(); final ClassInitializerTranslator classInitializerTranslator = new ClassInitializerTranslator(classDeclaration, context);
return classInitializerTranslator.generateInitializeMethod();
} }
@NotNull @NotNull
public static JsPropertyInitializer generateNamespaceInitializerMethod(@NotNull NamespaceDescriptor namespace, public static JsPropertyInitializer generateNamespaceInitializerMethod(@NotNull NamespaceDescriptor namespace,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new NamespaceInitializerTranslator(namespace, context)).generateInitializeMethod(); final NamespaceInitializerTranslator namespaceInitializerTranslator = new NamespaceInitializerTranslator(namespace, context);
return namespaceInitializerTranslator.generateInitializeMethod();
} }
@NotNull @NotNull
@@ -1,68 +0,0 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.initializer;
import com.google.dart.compiler.backend.js.ast.JsFunction;
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.NamingScope;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import java.util.List;
/**
* @author Pavel Talanov
*/
public abstract class AbstractInitializerTranslator extends AbstractTranslator {
@NotNull
private final InitializerVisitor visitor;
@NotNull
protected final NamingScope initializerMethodScope;
protected AbstractInitializerTranslator(@NotNull NamingScope scope, @NotNull TranslationContext context) {
super(context.contextWithScope(scope));
this.visitor = new InitializerVisitor();
this.initializerMethodScope = scope;
}
abstract protected JsFunction generateInitializerFunction();
@NotNull
public JsPropertyInitializer generateInitializeMethod() {
JsPropertyInitializer initializer = new JsPropertyInitializer();
initializer.setLabelExpr(Namer.initializeMethodReference());
initializer.setValueExpr(generateInitializerFunction());
return initializer;
}
@NotNull
protected List<JsStatement> translateClassInitializers(@NotNull JetClassOrObject declaration) {
return visitor.traverseClass(declaration, context());
}
@NotNull
protected List<JsStatement> translateNamespaceInitializers(@NotNull NamespaceDescriptor namespace) {
return visitor.traverseNamespace(namespace, context());
}
}
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -41,7 +42,7 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateArgum
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public final class ClassInitializerTranslator extends AbstractInitializerTranslator { public final class ClassInitializerTranslator extends AbstractTranslator {
@NotNull @NotNull
private final JetClassOrObject classDeclaration; private final JetClassOrObject classDeclaration;
@@ -51,13 +52,12 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla
public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) {
// Note: it's important we use scope for class descriptor because anonymous function used in property initializers // Note: it's important we use scope for class descriptor because anonymous function used in property initializers
// belong to the properties themselves // belong to the properties themselves
super(context.getScopeForDescriptor(getClassDescriptor(context.bindingContext(), classDeclaration)), context); super(context.newDeclaration(getConstructor(context.bindingContext(), classDeclaration)));
this.classDeclaration = classDeclaration; this.classDeclaration = classDeclaration;
} }
@Override
@NotNull @NotNull
protected JsFunction generateInitializerFunction() { public JsPropertyInitializer generateInitializeMethod() {
//TODO: it's inconsistent that we scope for class and function for constructor, currently have problems implementing better way //TODO: it's inconsistent that we scope for class and function for constructor, currently have problems implementing better way
ConstructorDescriptor primaryConstructor = getConstructor(bindingContext(), classDeclaration); ConstructorDescriptor primaryConstructor = getConstructor(bindingContext(), classDeclaration);
JsFunction result = context().getFunctionObject(primaryConstructor); JsFunction result = context().getFunctionObject(primaryConstructor);
@@ -65,14 +65,9 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla
// for properties declared as constructor parameters // for properties declared as constructor parameters
setParameters(result, translatePrimaryConstructorParameters()); setParameters(result, translatePrimaryConstructorParameters());
mayBeAddCallToSuperMethod(); mayBeAddCallToSuperMethod();
result.setBody(generateInitializerMethodBody()); initializerStatements.addAll((new InitializerVisitor()).traverseClass(classDeclaration, context()));
return result; result.getBody().getStatements().addAll(initializerStatements);
} return InitializerUtils.generateInitializeMethod(result);
@NotNull
private JsBlock generateInitializerMethodBody() {
initializerStatements.addAll(translateClassInitializers(classDeclaration));
return newBlock(initializerStatements);
} }
private void mayBeAddCallToSuperMethod() { private void mayBeAddCallToSuperMethod() {
@@ -85,7 +80,7 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla
private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall) { private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall) {
//TODO: can be problematic to maintain //TODO: can be problematic to maintain
JsName superMethodName = initializerMethodScope.jsScope().declareName(Namer.superMethodName()); JsName superMethodName = context().jsScope().declareName(Namer.superMethodName());
superMethodName.setObfuscatable(false); superMethodName.setObfuscatable(false);
List<JsExpression> arguments = translateArguments(superCall); List<JsExpression> arguments = translateArguments(superCall);
initializerStatements.add(convertToStatement(newInvocation(thisQualifiedReference(superMethodName), arguments))); initializerStatements.add(convertToStatement(newInvocation(thisQualifiedReference(superMethodName), arguments)));
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.translate.initializer;
import com.google.dart.compiler.backend.js.ast.JsFunction;
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
/**
* @author Pavel Talanov
*/
public final class InitializerUtils {
private InitializerUtils() {
}
@NotNull
public static JsPropertyInitializer generateInitializeMethod(@NotNull JsFunction initializerFunction) {
JsPropertyInitializer initializer = new JsPropertyInitializer();
initializer.setLabelExpr(Namer.initializeMethodReference());
initializer.setValueExpr(initializerFunction);
return initializer;
}
}
@@ -17,33 +17,39 @@
package org.jetbrains.k2js.translate.initializer; package org.jetbrains.k2js.translate.initializer;
import com.google.dart.compiler.backend.js.ast.JsFunction; import com.google.dart.compiler.backend.js.ast.JsFunction;
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newBlock; import java.util.List;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public final class NamespaceInitializerTranslator extends AbstractInitializerTranslator { public final class NamespaceInitializerTranslator {
@NotNull @NotNull
private final NamespaceDescriptor namespace; private final NamespaceDescriptor namespace;
@NotNull
private final TranslationContext namespaceContext;
public NamespaceInitializerTranslator(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) { public NamespaceInitializerTranslator(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) {
//NOTE:
super(context.getScopeForDescriptor(namespace), context);
this.namespace = namespace; this.namespace = namespace;
this.namespaceContext = context;
} }
@Override
@NotNull @NotNull
protected JsFunction generateInitializerFunction() { public JsPropertyInitializer generateInitializeMethod() {
//NOTE: namespace has no constructor JsFunction result = JsAstUtils.createFunctionWithEmptyBody(namespaceContext.jsScope());
JsFunction result = new JsFunction(initializerMethodScope.jsScope()); TranslationContext namespaceInitializerContext
result.setBody(newBlock(translateNamespaceInitializers(namespace))); = namespaceContext.innerContextWithGivenScopeAndBlock(result.getScope(), result.getBody());
return result; List<JsStatement> initializerStatements =
(new InitializerVisitor()).traverseNamespace(namespace, namespaceInitializerContext);
result.getBody().getStatements().addAll(initializerStatements);
return InitializerUtils.generateInitializeMethod(result);
} }
@@ -347,7 +347,7 @@ public final class BindingUtils {
return resolvedCall; return resolvedCall;
} }
public static ConstructorDescriptor getConstructor(BindingContext bindingContext, public static ConstructorDescriptor getConstructor(@NotNull BindingContext bindingContext,
@NotNull JetClassOrObject declaration) { @NotNull JetClassOrObject declaration) {
ConstructorDescriptor primaryConstructor = ConstructorDescriptor primaryConstructor =
getClassDescriptor(bindingContext, declaration).getUnsubstitutedPrimaryConstructor(); getClassDescriptor(bindingContext, declaration).getUnsubstitutedPrimaryConstructor();
@@ -264,4 +264,11 @@ public final class JsAstUtils {
} }
return result; return result;
} }
@NotNull
public static JsFunction createFunctionWithEmptyBody(@NotNull JsScope parent) {
JsFunction correspondingFunction = new JsFunction(parent);
correspondingFunction.setBody(new JsBlock());
return correspondingFunction;
}
} }
@@ -0,0 +1,19 @@
package foo
class A() {
fun foo() = 1
fun a(f : A.()->Int) : Int {
return f()
}
}
var d = 0
val p : A.()->Int = {
d = foo()
d++
}
val c = A().a(p)
fun box() = (c == 1)
@@ -0,0 +1,19 @@
package foo
class A() {
fun lold() = true
val p : ()->Boolean
{
$p = {{lold()}()}
}
}
fun box() : Boolean {
return A().p()
}
fun main(arg : Array<String>) {
println(box())
}
@@ -0,0 +1,7 @@
package foo
fun lold() = true
val p = {{lold()}()}
fun box() = p() && foo.p()
@@ -0,0 +1,6 @@
package foo
var p = 0
val c = p++ // creates temporary value
fun box() = (p == 1) && (c == 0)