diff --git a/.idea/ant.xml b/.idea/ant.xml
index 24adafcd5c7..ed038767c6b 100644
--- a/.idea/ant.xml
+++ b/.idea/ant.xml
@@ -10,14 +10,6 @@
-
-
-
-
-
-
-
-
diff --git a/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java b/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java
index c1395d86f5f..8617f13f719 100644
--- a/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java
+++ b/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java
@@ -18,9 +18,7 @@ package org.jetbrains.jet.buildtools.core;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.compiler.CompileEnvironment;
-import org.jetbrains.jet.compiler.CompileEnvironmentException;
-import org.jetbrains.jet.compiler.CompilerPlugin;
+import org.jetbrains.jet.compiler.*;
import org.jetbrains.jet.compiler.messages.MessageCollector;
import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
@@ -42,26 +40,29 @@ public class BytecodeCompiler {
/**
- * Creates new instance of {@link CompileEnvironment} instance using the arguments specified.
+ * Creates new instance of {@link org.jetbrains.jet.compiler.CompileEnvironmentConfiguration} instance using the arguments specified.
*
* @param stdlib path to "kotlin-runtime.jar", only used if not null and not empty
* @param classpath compilation classpath, only used if not null and not empty
*
* @return compile environment instance
*/
- private CompileEnvironment env( String stdlib, String[] classpath ) {
- CompileEnvironment env = new CompileEnvironment(MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR, CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR));
+ private CompileEnvironmentConfiguration env( String stdlib, String[] classpath ) {
+ CompilerDependencies dependencies = CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR);
+ JetCoreEnvironment environment = new JetCoreEnvironment(CompileEnvironmentUtil.createMockDisposable(), dependencies);
+ CompileEnvironmentConfiguration env = new CompileEnvironmentConfiguration(environment, dependencies, MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR);
if (( stdlib != null ) && ( stdlib.trim().length() > 0 )) {
- env.setStdlib( stdlib );
+ File file = new File(stdlib);
+ CompileEnvironmentUtil.addToClasspath(env.getEnvironment(), file);
}
if (( classpath != null ) && ( classpath.length > 0 )) {
- env.addToClasspath( classpath );
+ CompileEnvironmentUtil.addToClasspath(env.getEnvironment(), classpath);
}
// lets register any compiler plugins
- env.getEnvironment().getCompilerPlugins().addAll(getCompilerPlugins());
+ env.getCompilerPlugins().addAll(getCompilerPlugins());
return env;
}
@@ -92,7 +93,8 @@ public class BytecodeCompiler {
*/
public void sourcesToDir ( @NotNull String src, @NotNull String output, @Nullable String stdlib, @Nullable String[] classpath ) {
try {
- boolean success = env( stdlib, classpath ).compileBunchOfSources( src, null, output, true /* Last arg is ignored anyway */ );
+ boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(env(stdlib, classpath), src, null, output, true
+ /* Last arg is ignored anyway */);
if ( ! success ) {
throw new CompileEnvironmentException( errorMessage( src, false ));
}
@@ -114,7 +116,7 @@ public class BytecodeCompiler {
*/
public void sourcesToJar ( @NotNull String src, @NotNull String jar, boolean includeRuntime, @Nullable String stdlib, @Nullable String[] classpath ) {
try {
- boolean success = env( stdlib, classpath ).compileBunchOfSources( src, jar, null, includeRuntime );
+ boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(env(stdlib, classpath), src, jar, null, includeRuntime);
if ( ! success ) {
throw new CompileEnvironmentException( errorMessage( src, false ));
}
@@ -136,7 +138,8 @@ public class BytecodeCompiler {
*/
public void moduleToJar ( @NotNull String module, @NotNull String jar, boolean includeRuntime, @Nullable String stdlib, @Nullable String[] classpath ) {
try {
- boolean success = env( stdlib, classpath ).compileModuleScript( module, jar, null, includeRuntime);
+ CompileEnvironmentConfiguration env = env(stdlib, classpath);
+ boolean success = KotlinToJVMBytecodeCompiler.compileModuleScript(env, module, jar, null, includeRuntime);
if ( ! success ) {
throw new CompileEnvironmentException( errorMessage( module, false ));
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
index 89eddf97855..ea431b29b9b 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java
@@ -16,7 +16,6 @@
package org.jetbrains.jet.codegen;
-import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
@@ -148,7 +147,7 @@ public abstract class ClassBodyCodegen {
private void generateStaticInitializer() {
if (staticInitializerChunks.size() > 0) {
final MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | Opcodes.ACC_STATIC,"", "()V", null, null);
- if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java
index 4fda5422ef4..12b51fe7ef7 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilder.java
@@ -21,27 +21,24 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
-import org.objectweb.asm.*;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
public abstract class ClassBuilder {
public static class Concrete extends ClassBuilder {
private final ClassVisitor v;
- private final boolean stubs;
- public Concrete(ClassVisitor v, boolean stubs) {
+ public Concrete(ClassVisitor v) {
this.v = v;
- this.stubs = stubs;
}
@Override
public ClassVisitor getVisitor() {
return v;
}
-
- @Override
- public Mode generateCode() {
- return stubs ? Mode.STUBS : Mode.FULL;
- }
}
public FieldVisitor newField(@Nullable PsiElement origin,
int access,
@@ -88,15 +85,4 @@ public abstract class ClassBuilder {
public void visitInnerClass(String name, String outerName, String innerName, int access) {
getVisitor().visitInnerClass(name, outerName, innerName, access);
}
-
- public enum Mode {
- /** Full function bodies */
- FULL,
- /** Only function signatures */
- SIGNATURES,
- /** Function with stub bodies: just throw exception */
- STUBS,
- }
-
- public abstract Mode generateCode();
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java
index 06604f797ba..485c049037b 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactories.java
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen;
+import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor;
@@ -28,9 +29,15 @@ import java.io.StringWriter;
public class ClassBuilderFactories {
public static ClassBuilderFactory TEXT = new ClassBuilderFactory() {
+ @NotNull
+ @Override
+ public ClassBuilderMode getClassBuilderMode() {
+ return ClassBuilderMode.FULL;
+ }
+
@Override
public ClassBuilder newClassBuilder() {
- return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter())), false);
+ return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter())));
}
@Override
@@ -51,6 +58,12 @@ public class ClassBuilderFactories {
public static ClassBuilderFactory binaries(final boolean stubs) {
return new ClassBuilderFactory() {
+ @NotNull
+ @Override
+ public ClassBuilderMode getClassBuilderMode() {
+ return stubs ? ClassBuilderMode.STUBS : ClassBuilderMode.FULL;
+ }
+
@Override
public ClassBuilder newClassBuilder() {
return new ClassBuilder.Concrete(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS){
@@ -64,7 +77,7 @@ public class ClassBuilderFactories {
return "java/lang/Object";
}
}
- }, stubs);
+ });
}
@Override
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java
index e46d50c4fe2..9806778934b 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderFactory.java
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen;
+import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor;
@@ -26,6 +27,8 @@ import java.io.StringWriter;
* @author max
*/
public interface ClassBuilderFactory {
+ @NotNull
+ ClassBuilderMode getClassBuilderMode();
ClassBuilder newClassBuilder();
String asText(ClassBuilder builder);
byte[] asBytes(ClassBuilder builder);
diff --git a/confluence/src/main/java/com/intellij/lexer/Foo.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderMode.java
similarity index 70%
rename from confluence/src/main/java/com/intellij/lexer/Foo.java
rename to compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderMode.java
index afacc1e12c5..096391c2be8 100644
--- a/confluence/src/main/java/com/intellij/lexer/Foo.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBuilderMode.java
@@ -14,10 +14,16 @@
* limitations under the License.
*/
-package com.intellij.lexer;
+package org.jetbrains.jet.codegen;
/**
- * @author abreslav
- */
-public class Foo {
+* @author Stepan Koltsov
+*/
+public enum ClassBuilderMode {
+ /** Full function bodies */
+ FULL,
+ /** Only function signatures */
+ SIGNATURES,
+ /** Function with stub bodies: just throw exception */
+ STUBS,
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java
index f596669dff8..a585ef6b737 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java
@@ -40,7 +40,7 @@ public class ClassCodegen {
final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state.getInjector().getJetTypeMapper());
- if (classBuilder.generateCode() == ClassBuilder.Mode.SIGNATURES) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder);
}
@@ -54,7 +54,7 @@ public class ClassCodegen {
}
}
- if (classBuilder.generateCode() != ClassBuilder.Mode.SIGNATURES) {
+ if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors, classBuilder);
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java
index 8f4c2bdd3f3..46fa697d5cb 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java
@@ -170,10 +170,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
cv.newField(fun, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "$instance", classDescr, null, null);
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]);
- if (cv.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (cv.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
mv.visitInsn(DUP);
@@ -211,10 +211,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
return;
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getAsmMethod().getDescriptor(), null, new String[0]);
- if (cv.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- if (cv.generateCode() == ClassBuilder.Mode.FULL) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -296,10 +296,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final Method constructor = new Method("", Type.VOID_TYPE, argTypes);
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "", constructor.getDescriptor(), null, new String[0]);
- if (cv.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (cv.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
index 7238ed6bbb3..0a828995516 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
@@ -124,7 +124,7 @@ public class FunctionCodegen {
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getAsmMethod().getName(), jvmSignature.getAsmMethod().getDescriptor(), jvmSignature.getGenericsSignature(), null);
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(functionDescriptor);
- if(v.generateCode() != ClassBuilder.Mode.SIGNATURES) {
+ if(state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
int start = 0;
if (needJetAnnotations) {
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
@@ -169,12 +169,12 @@ public class FunctionCodegen {
}
}
- if (!isAbstract && v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (!isAbstract && state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- if (!isAbstract && v.generateCode() == ClassBuilder.Mode.FULL) {
+ if (!isAbstract && state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
Label methodBegin = new Label();
@@ -345,10 +345,10 @@ public class FunctionCodegen {
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
final MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC), isConstructor ? "" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = owner.prepareFrame(state.getInjector().getJetTypeMapper());
@@ -474,10 +474,10 @@ public class FunctionCodegen {
int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO.
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
Type[] argTypes = overriden.getArgumentTypes();
@@ -515,10 +515,10 @@ public class FunctionCodegen {
int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO.
final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null);
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
Type[] argTypes = method.getArgumentTypes();
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java
index fd583a67fee..33bb005af93 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java
@@ -49,6 +49,8 @@ public class GenerationState {
private final List files;
@NotNull
private final InjectorForJvmCodegen injector;
+ @NotNull
+ private final ClassBuilderMode classBuilderMode;
public GenerationState(Project project, ClassBuilderFactory builderFactory, AnalyzeExhaust analyzeExhaust, List files) {
@@ -61,9 +63,10 @@ public class GenerationState {
this.progress = progress;
this.analyzeExhaust = exhaust;
this.files = files;
+ this.classBuilderMode = builderFactory.getClassBuilderMode();
this.injector = new InjectorForJvmCodegen(
analyzeExhaust.getStandardLibrary(), analyzeExhaust.getBindingContext(),
- this.files, project, compilerSpecialMode, this, builderFactory);
+ this.files, project, compilerSpecialMode, builderFactory.getClassBuilderMode(), this, builderFactory);
}
@NotNull
@@ -83,6 +86,11 @@ public class GenerationState {
return analyzeExhaust.getBindingContext();
}
+ @NotNull
+ public ClassBuilderMode getClassBuilderMode() {
+ return classBuilderMode;
+ }
+
public ClassCodegen forClass() {
return new ClassCodegen(this);
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index 71719b9a217..7a7b2cd023d 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -296,10 +296,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Type[] argTypes = method.getArgumentTypes();
MethodVisitor mv = v.newMethod(null, ACC_PUBLIC| ACC_BRIDGE| ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -327,10 +327,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method originalMethod = originalSignature.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature.getPropertyTypeKotlinSignature(), originalSignature.getJvmMethodSignature().getKotlinTypeParameter());
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -353,10 +353,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method originalMethod = originalSignature2.getJvmMethodSignature().getAsmMethod();
MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_BRIDGE | ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
PropertyCodegen.generateJetPropertyAnnotation(mv, originalSignature2.getPropertyTypeKotlinSignature(), originalSignature2.getJvmMethodSignature().getKotlinTypeParameter());
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -531,7 +531,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
int flags = ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), constructorMethod.getGenericsSignature(), null);
- if (v.generateCode() == ClassBuilder.Mode.SIGNATURES) return;
+ if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) return;
AnnotationVisitor jetConstructorVisitor = mv.visitAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getDescriptor(), true);
if (constructorDescriptor == null) {
@@ -558,7 +558,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
return;
}
@@ -733,10 +733,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod();
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
codegen.generateThisOrOuter(descriptor);
@@ -872,10 +872,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
int flags = ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(constructor, flags, "", method.getSignature().getAsmMethod().getDescriptor(), null, null);
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubCode(mv);
}
- else if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration()));
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
index 3508bb9eb03..c19b4e25aa9 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java
@@ -65,6 +65,7 @@ public class JetTypeMapper {
public BindingContext bindingContext;
private ClosureAnnotator closureAnnotator;
private CompilerSpecialMode compilerSpecialMode;
+ private ClassBuilderMode classBuilderMode;
@Inject
@@ -87,6 +88,11 @@ public class JetTypeMapper {
this.compilerSpecialMode = compilerSpecialMode;
}
+ @Inject
+ public void setClassBuilderMode(ClassBuilderMode classBuilderMode) {
+ this.classBuilderMode = classBuilderMode;
+ }
+
@PostConstruct
public void init() {
initKnownTypes();
@@ -335,6 +341,9 @@ public class JetTypeMapper {
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (ErrorUtils.isError(descriptor)) {
+ if (classBuilderMode != ClassBuilderMode.SIGNATURES) {
+ throw new IllegalStateException("error types are not allowed when classBuilderMode = " + classBuilderMode);
+ }
Type asmType = Type.getObjectType("error/NonExistentClass");
if (signatureVisitor != null) {
visitAsmType(signatureVisitor, asmType, true);
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
index ca2fe73e250..2a3338c7510 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
@@ -92,7 +92,7 @@ public class NamespaceCodegen {
private void generateStaticInitializers(JetFile namespace) {
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "", "()V", null, null);
- if (v.generateCode() == ClassBuilder.Mode.FULL) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = new FrameMap();
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
index f8070e10c35..d9d4e9f9373 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
@@ -182,10 +182,10 @@ public class PropertyCodegen {
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor.getGetter());
}
- if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
+ if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
if(propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode();
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv);
}
else {
@@ -266,10 +266,10 @@ public class PropertyCodegen {
AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor.getSetter());
}
- if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
+ if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) {
if(propertyDescriptor.getModality() != Modality.ABSTRACT) {
mv.visitCode();
- if (v.generateCode() == ClassBuilder.Mode.STUBS) {
+ if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
StubCodegen.generateStubThrow(mv);
}
else {
diff --git a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java
index ddbaad7230d..30a4db600be 100644
--- a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java
+++ b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java
@@ -23,6 +23,7 @@ import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
+import org.jetbrains.jet.codegen.ClassBuilderMode;
import org.jetbrains.jet.codegen.ClosureAnnotator;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -42,9 +43,11 @@ public class InjectorForJetTypeMapper {
) {
this.jetTypeMapper = new JetTypeMapper();
CompilerSpecialMode compilerSpecialMode = CompilerSpecialMode.REGULAR;
+ ClassBuilderMode classBuilderMode = ClassBuilderMode.FULL;
ClosureAnnotator closureAnnotator = new ClosureAnnotator();
this.jetTypeMapper.setBindingContext(bindingContext);
+ this.jetTypeMapper.setClassBuilderMode(classBuilderMode);
this.jetTypeMapper.setClosureAnnotator(closureAnnotator);
this.jetTypeMapper.setCompilerSpecialMode(compilerSpecialMode);
this.jetTypeMapper.setStandardLibrary(jetStandardLibrary);
diff --git a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java
index 626c27bbf54..e54bef57e52 100644
--- a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java
@@ -23,6 +23,7 @@ import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
+import org.jetbrains.jet.codegen.ClassBuilderMode;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.JetTypeMapper;
@@ -35,6 +36,7 @@ import java.util.List;
import org.jetbrains.jet.lang.psi.JetFile;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
+import org.jetbrains.jet.codegen.ClassBuilderMode;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.annotations.NotNull;
@@ -54,6 +56,7 @@ public class InjectorForJvmCodegen {
@NotNull List listOfJetFile,
@NotNull Project project,
@NotNull CompilerSpecialMode compilerSpecialMode,
+ @NotNull ClassBuilderMode classBuilderMode,
@NotNull GenerationState generationState,
@NotNull ClassBuilderFactory classBuilderFactory
) {
@@ -65,6 +68,7 @@ public class InjectorForJvmCodegen {
ClosureAnnotator closureAnnotator = new ClosureAnnotator();
this.jetTypeMapper.setBindingContext(bindingContext);
+ this.jetTypeMapper.setClassBuilderMode(classBuilderMode);
this.jetTypeMapper.setClosureAnnotator(closureAnnotator);
this.jetTypeMapper.setCompilerSpecialMode(compilerSpecialMode);
this.jetTypeMapper.setStandardLibrary(jetStandardLibrary);
diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java
index 8be718f846a..54a6eef6608 100644
--- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java
+++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java
@@ -20,11 +20,11 @@ import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
import com.sampullara.cli.Args;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.compiler.CompileEnvironment;
-import org.jetbrains.jet.compiler.CompileEnvironmentException;
-import org.jetbrains.jet.compiler.CompilerPlugin;
+import org.jetbrains.jet.compiler.*;
import org.jetbrains.jet.compiler.messages.CompilerMessageLocation;
import org.jetbrains.jet.compiler.messages.CompilerMessageSeverity;
import org.jetbrains.jet.compiler.messages.MessageCollector;
@@ -135,23 +135,30 @@ public class KotlinCompiler {
runtimeJar = null;
}
- CompilerDependencies dependencies = new CompilerDependencies(mode, jdkHeadersJar,runtimeJar);
+ CompilerDependencies dependencies = new CompilerDependencies(mode, jdkHeadersJar, runtimeJar);
PrintingMessageCollector messageCollector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose);
- CompileEnvironment environment = new CompileEnvironment(messageCollector, dependencies);
+ Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable();
+
+ JetCoreEnvironment environment = new JetCoreEnvironment(rootDisposable, dependencies);
+ CompileEnvironmentConfiguration configuration = new CompileEnvironmentConfiguration(environment, dependencies, messageCollector);
try {
- configureEnvironment(environment, arguments);
+ configureEnvironment(configuration, arguments);
boolean noErrors;
if (arguments.module != null) {
- noErrors = environment.compileModuleScript(arguments.module, arguments.jar, arguments.outputDir, arguments.includeRuntime);
+ noErrors = KotlinToJVMBytecodeCompiler.compileModuleScript(configuration,
+ arguments.module, arguments.jar, arguments.outputDir,
+ arguments.includeRuntime);
}
else {
// TODO ideally we'd unify to just having a single field that supports multiple files/dirs
if (arguments.getSourceDirs() != null) {
- noErrors = environment.compileBunchOfSourceDirectories(arguments.getSourceDirs(), arguments.jar, arguments.outputDir, arguments.includeRuntime);
+ noErrors = KotlinToJVMBytecodeCompiler.compileBunchOfSourceDirectories(configuration,
+ arguments.getSourceDirs(), arguments.jar, arguments.outputDir, arguments.includeRuntime);
}
else {
- noErrors = environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime);
+ noErrors = KotlinToJVMBytecodeCompiler.compileBunchOfSources(configuration,
+ arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime);
}
}
return noErrors ? OK : COMPILATION_ERROR;
@@ -161,7 +168,7 @@ public class KotlinCompiler {
return INTERNAL_ERROR;
}
finally {
- environment.dispose();
+ Disposer.dispose(rootDisposable);
messageCollector.printToErrStream();
}
}
@@ -228,20 +235,20 @@ public class KotlinCompiler {
* Strategy method to configure the environment, allowing compiler
* based tools to customise their own plugins
*/
- protected void configureEnvironment(CompileEnvironment environment, CompilerArguments arguments) {
+ protected void configureEnvironment(CompileEnvironmentConfiguration configuration, CompilerArguments arguments) {
// install any compiler plugins
List plugins = arguments.getCompilerPlugins();
if (plugins != null) {
- environment.getEnvironment().getCompilerPlugins().addAll(plugins);
+ configuration.getCompilerPlugins().addAll(plugins);
}
- if (environment.getCompilerDependencies().getRuntimeJar() != null) {
- environment.addToClasspath(environment.getCompilerDependencies().getRuntimeJar());
+ if (configuration.getCompilerDependencies().getRuntimeJar() != null) {
+ CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), configuration.getCompilerDependencies().getRuntimeJar());
}
if (arguments.classpath != null) {
final Iterable classpath = Splitter.on(File.pathSeparatorChar).split(arguments.classpath);
- environment.addToClasspath(Iterables.toArray(classpath, String.class));
+ CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), Iterables.toArray(classpath, String.class));
}
}
diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java
deleted file mode 100644
index ac22091f949..00000000000
--- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java
+++ /dev/null
@@ -1,243 +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.jet.compiler;
-
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.testFramework.LightVirtualFile;
-import com.intellij.util.LocalTimeCounter;
-import jet.modules.Module;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.codegen.ClassFileFactory;
-import org.jetbrains.jet.codegen.GeneratedClassLoader;
-import org.jetbrains.jet.codegen.GenerationState;
-import org.jetbrains.jet.compiler.messages.MessageCollector;
-import org.jetbrains.jet.lang.psi.JetFile;
-import org.jetbrains.jet.lang.psi.JetPsiUtil;
-import org.jetbrains.jet.lang.resolve.FqName;
-import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
-import org.jetbrains.jet.lang.resolve.java.JvmAbi;
-import org.jetbrains.jet.plugin.JetLanguage;
-import org.jetbrains.jet.plugin.JetMainDetector;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.util.List;
-
-/**
- * The environment for compiling a bunch of source files or
- *
- * @author yole
- */
-public class CompileEnvironment {
- private final Disposable rootDisposable;
- private JetCoreEnvironment environment;
-
- private final MessageCollector messageCollector;
-
- @NotNull
- private final CompilerDependencies compilerDependencies;
-
- /**
- * NOTE: It's very important to call dispose for every object of this class or there will be memory leaks.
- * @see Disposer
- */
- public CompileEnvironment(@NotNull MessageCollector messageCollector, @NotNull CompilerDependencies compilerDependencies) {
- this.messageCollector = messageCollector;
- this.compilerDependencies = compilerDependencies;
- this.rootDisposable = new Disposable() {
- @Override
- public void dispose() {
- }
- };
- this.environment = new JetCoreEnvironment(rootDisposable, compilerDependencies);
- }
-
-
- public void dispose() {
- Disposer.dispose(rootDisposable);
- }
-
- public boolean compileModuleScript(String moduleScriptFile, @Nullable String jarPath, @Nullable String outputDir, boolean jarRuntime) {
- List modules = CompileEnvironmentUtil.loadModuleScript(moduleScriptFile, messageCollector);
-
- if (modules == null) {
- throw new CompileEnvironmentException("Module script " + moduleScriptFile + " compilation failed");
- }
-
- if (modules.isEmpty()) {
- throw new CompileEnvironmentException("No modules where defined by " + moduleScriptFile);
- }
-
- final String directory = new File(moduleScriptFile).getParent();
- for (Module moduleBuilder : modules) {
- if (compilerDependencies.getRuntimeJar() != null) {
- addToClasspath(compilerDependencies.getRuntimeJar());
- }
- ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory);
- if (moduleFactory == null) {
- return false;
- }
- if (outputDir != null) {
- CompileEnvironmentUtil.writeToOutputDirectory(moduleFactory, outputDir);
- }
- else {
- String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath();
- try {
- CompileEnvironmentUtil.writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime);
- }
- catch (FileNotFoundException e) {
- throw new CompileEnvironmentException("Invalid jar path " + path, e);
- }
- }
- }
- return true;
- }
-
- public ClassFileFactory compileModule(Module moduleBuilder, String directory) {
- if (moduleBuilder.getSourceFiles().isEmpty()) {
- throw new CompileEnvironmentException("No source files where defined");
- }
-
- for (String sourceFile : moduleBuilder.getSourceFiles()) {
- File source = new File(sourceFile);
- if (!source.isAbsolute()) {
- source = new File(directory, sourceFile);
- }
-
- if (!source.exists()) {
- throw new CompileEnvironmentException("'" + source + "' does not exist");
- }
-
- environment.addSources(source.getPath());
- }
- for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
- environment.addToClasspath(new File(classpathRoot));
- }
-
- CompileEnvironmentUtil.ensureRuntime(environment, compilerDependencies);
-
- return analyze();
- }
-
- public ClassLoader compileText(String code) {
- environment.addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code));
-
- ClassFileFactory factory = analyze();
- if (factory == null) {
- return null;
- }
- return new GeneratedClassLoader(factory);
- }
-
- public boolean compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) {
- environment.addSources(sourceFileOrDir);
-
- return compileBunchOfSources(jar, outputDir, includeRuntime);
- }
-
- public boolean compileBunchOfSourceDirectories(List sources, String jar, String outputDir, boolean includeRuntime) {
- for (String source : sources) {
- environment.addSources(source);
- }
-
- return compileBunchOfSources(jar, outputDir, includeRuntime);
- }
-
- private boolean compileBunchOfSources(String jar, String outputDir, boolean includeRuntime) {
- FqName mainClass = null;
- for (JetFile file : environment.getSourceFiles()) {
- if (JetMainDetector.hasMain(file.getDeclarations())) {
- FqName fqName = JetPsiUtil.getFQName(file);
- mainClass = fqName.child(JvmAbi.PACKAGE_CLASS);
- break;
- }
- }
-
- CompileEnvironmentUtil.ensureRuntime(environment, compilerDependencies);
-
- ClassFileFactory factory = analyze();
- if (factory == null) {
- return false;
- }
-
- if (jar != null) {
- try {
- CompileEnvironmentUtil.writeToJar(factory, new FileOutputStream(jar), mainClass, includeRuntime);
- } catch (FileNotFoundException e) {
- throw new CompileEnvironmentException("Invalid jar path " + jar, e);
- }
- }
- else if (outputDir != null) {
- CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir);
- }
- else {
- throw new CompileEnvironmentException("Output directory or jar file is not specified - no files will be saved to the disk");
- }
- return true;
- }
-
- private ClassFileFactory analyze() {
- boolean stubs = compilerDependencies.getCompilerSpecialMode().isStubs();
- GenerationState generationState =
- KotlinToJVMBytecodeCompiler
- .analyzeAndGenerate(environment, compilerDependencies, messageCollector, stubs);
- if (generationState == null) {
- return null;
- }
- return generationState.getFactory();
- }
-
- /**
- * Add path specified to the compilation environment.
- * @param paths paths to add
- */
- public void addToClasspath(File ... paths) {
- for (File path : paths) {
- if (!path.exists()) {
- throw new CompileEnvironmentException("'" + path + "' does not exist");
- }
- environment.addToClasspath(path);
- }
- }
-
- /**
- * Add path specified to the compilation environment.
- * @param paths paths to add
- */
- public void addToClasspath(String ... paths) {
- for (String path : paths) {
- addToClasspath( new File(path));
- }
- }
-
- public void setStdlib(String stdlib) {
- File file = new File(stdlib);
- addToClasspath(file);
- }
-
- public JetCoreEnvironment getEnvironment() {
- return environment;
- }
-
- @NotNull
- public CompilerDependencies getCompilerDependencies() {
- return compilerDependencies;
- }
-}
diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentConfiguration.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentConfiguration.java
new file mode 100644
index 00000000000..cf57bee50b2
--- /dev/null
+++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentConfiguration.java
@@ -0,0 +1,65 @@
+/*
+ * 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.jet.compiler;
+
+import com.google.common.collect.Lists;
+import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.compiler.messages.MessageCollector;
+import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
+
+import java.util.List;
+
+/**
+ * @author abreslav
+ */
+public class CompileEnvironmentConfiguration {
+ private final JetCoreEnvironment environment;
+ private final CompilerDependencies compilerDependencies;
+ private final MessageCollector messageCollector;
+
+ private List compilerPlugins = Lists.newArrayList();
+
+ /**
+ * NOTE: It's very important to call dispose for every object of this class or there will be memory leaks.
+ * @see Disposer
+ */
+ public CompileEnvironmentConfiguration(@NotNull JetCoreEnvironment environment,
+ @NotNull CompilerDependencies compilerDependencies, @NotNull MessageCollector messageCollector) {
+ this.messageCollector = messageCollector;
+ this.compilerDependencies = compilerDependencies;
+ this.environment = environment;
+ }
+
+ public JetCoreEnvironment getEnvironment() {
+ return environment;
+ }
+
+ @NotNull
+ public CompilerDependencies getCompilerDependencies() {
+ return compilerDependencies;
+ }
+
+ @NotNull
+ public MessageCollector getMessageCollector() {
+ return messageCollector;
+ }
+
+ public List getCompilerPlugins() {
+ return compilerPlugins;
+ }
+}
diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java
index eaf0af30966..ca803c0549f 100644
--- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java
+++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java
@@ -51,9 +51,17 @@ import java.util.jar.*;
* @author abreslav
*/
public class CompileEnvironmentUtil {
+ public static Disposable createMockDisposable() {
+ return new Disposable() {
+ @Override
+ public void dispose() {
+ }
+ };
+ }
+
@Nullable
public static File getUnpackedRuntimePath() {
- URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class");
+ URL url = CompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class");
if (url != null && url.getProtocol().equals("file")) {
return new File(url.getPath()).getParentFile().getParentFile();
}
@@ -62,7 +70,7 @@ public class CompileEnvironmentUtil {
@Nullable
public static File getRuntimeJarPath() {
- URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class");
+ URL url = CompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class");
if (url != null && url.getProtocol().equals("jar")) {
String path = url.getPath();
return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/")));
@@ -165,7 +173,7 @@ public class CompileEnvironmentUtil {
scriptEnvironment.addSources(moduleFile);
GenerationState generationState = KotlinToJVMBytecodeCompiler
- .analyzeAndGenerate(scriptEnvironment, dependencies, messageCollector, false);
+ .analyzeAndGenerate(new CompileEnvironmentConfiguration(scriptEnvironment, dependencies, messageCollector), false);
if (generationState == null) {
return null;
}
@@ -187,7 +195,7 @@ public class CompileEnvironmentUtil {
}
}
else {
- loader = new GeneratedClassLoader(factory, CompileEnvironment.class.getClassLoader());
+ loader = new GeneratedClassLoader(factory, CompileEnvironmentConfiguration.class.getClassLoader());
}
try {
Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS);
@@ -301,4 +309,29 @@ public class CompileEnvironmentUtil {
}
}
}
+
+ /**
+ * Add path specified to the compilation environment.
+ * @param environment compilation environment to add to
+ * @param paths paths to add
+ */
+ public static void addToClasspath(JetCoreEnvironment environment, File ... paths) {
+ for (File path : paths) {
+ if (!path.exists()) {
+ throw new CompileEnvironmentException("'" + path + "' does not exist");
+ }
+ environment.addToClasspath(path);
+ }
+ }
+
+ /**
+ * Add path specified to the compilation environment.
+ * @param environment compilation environment to add to
+ * @param paths paths to add
+ */
+ public static void addToClasspath(JetCoreEnvironment environment, String ... paths) {
+ for (String path : paths) {
+ addToClasspath(environment, new File(path));
+ }
+ }
}
diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/JetCoreEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/JetCoreEnvironment.java
index c3f24f3179e..bd8eb357ccf 100644
--- a/compiler/cli/src/org/jetbrains/jet/compiler/JetCoreEnvironment.java
+++ b/compiler/cli/src/org/jetbrains/jet/compiler/JetCoreEnvironment.java
@@ -46,7 +46,6 @@ import java.util.List;
*/
public class JetCoreEnvironment extends JavaCoreEnvironment {
private final List sourceFiles = new ArrayList();
- private List compilerPlugins = new ArrayList();
public JetCoreEnvironment(Disposable parentDisposable, @NotNull CompilerDependencies compilerDependencies) {
super(parentDisposable);
@@ -138,14 +137,6 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
return sourceFiles;
}
- public List getCompilerPlugins() {
- return compilerPlugins;
- }
-
- public void setCompilerPlugins(List compilerPlugins) {
- this.compilerPlugins = compilerPlugins;
- }
-
public void addToClasspathFromClassLoader(ClassLoader loader) {
ClassLoader parent = loader.getParent();
if(parent != null)
diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java
index ecc239820ad..7e6af64de21 100644
--- a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java
+++ b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java
@@ -25,12 +25,13 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.util.LocalTimeCounter;
+import jet.modules.Module;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
-import org.jetbrains.jet.codegen.ClassBuilderFactories;
-import org.jetbrains.jet.codegen.CompilationErrorHandler;
-import org.jetbrains.jet.codegen.GenerationState;
+import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.compiler.messages.CompilerMessageLocation;
import org.jetbrains.jet.compiler.messages.CompilerMessageSeverity;
import org.jetbrains.jet.compiler.messages.MessageCollector;
@@ -41,12 +42,19 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
+import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
-import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
+import org.jetbrains.jet.lang.resolve.java.JvmAbi;
+import org.jetbrains.jet.plugin.JetLanguage;
+import org.jetbrains.jet.plugin.JetMainDetector;
import org.jetbrains.jet.utils.Progress;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.util.Collection;
import java.util.List;
@@ -57,15 +65,169 @@ import java.util.List;
public class KotlinToJVMBytecodeCompiler {
@Nullable
- public static GenerationState analyzeAndGenerate(
- JetCoreEnvironment environment,
- CompilerDependencies dependencies,
+ public static ClassFileFactory compileModule(
+ CompileEnvironmentConfiguration configuration,
+ Module moduleBuilder,
+ String directory
+ ) {
+ if (moduleBuilder.getSourceFiles().isEmpty()) {
+ throw new CompileEnvironmentException("No source files where defined");
+ }
- final MessageCollector messageCollector,
+ for (String sourceFile : moduleBuilder.getSourceFiles()) {
+ File source = new File(sourceFile);
+ if (!source.isAbsolute()) {
+ source = new File(directory, sourceFile);
+ }
+
+ if (!source.exists()) {
+ throw new CompileEnvironmentException("'" + source + "' does not exist");
+ }
+
+ configuration.getEnvironment().addSources(source.getPath());
+ }
+ for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
+ configuration.getEnvironment().addToClasspath(new File(classpathRoot));
+ }
+
+ CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getCompilerDependencies());
+
+ GenerationState generationState = analyzeAndGenerate(configuration);
+ if (generationState == null) {
+ return null;
+ }
+ return generationState.getFactory();
+ }
+
+ public static boolean compileModuleScript(
+ CompileEnvironmentConfiguration configuration,
+
+ @NotNull String moduleScriptFile,
+ @Nullable String jarPath,
+ @Nullable String outputDir,
+ boolean jarRuntime) {
+ List modules = CompileEnvironmentUtil.loadModuleScript(moduleScriptFile, configuration.getMessageCollector());
+
+ if (modules == null) {
+ throw new CompileEnvironmentException("Module script " + moduleScriptFile + " compilation failed");
+ }
+
+ if (modules.isEmpty()) {
+ throw new CompileEnvironmentException("No modules where defined by " + moduleScriptFile);
+ }
+
+ final String directory = new File(moduleScriptFile).getParent();
+ for (Module moduleBuilder : modules) {
+ // TODO: this should be done only once for the environment
+ if (configuration.getCompilerDependencies().getRuntimeJar() != null) {
+ CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), configuration.getCompilerDependencies().getRuntimeJar());
+ }
+ ClassFileFactory moduleFactory = KotlinToJVMBytecodeCompiler.compileModule(configuration, moduleBuilder, directory);
+ if (moduleFactory == null) {
+ return false;
+ }
+ if (outputDir != null) {
+ CompileEnvironmentUtil.writeToOutputDirectory(moduleFactory, outputDir);
+ }
+ else {
+ String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath();
+ try {
+ CompileEnvironmentUtil.writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime);
+ }
+ catch (FileNotFoundException e) {
+ throw new CompileEnvironmentException("Invalid jar path " + path, e);
+ }
+ }
+ }
+ return true;
+ }
+
+ private static boolean compileBunchOfSources(
+ CompileEnvironmentConfiguration configuration,
+
+ String jar,
+ String outputDir,
+ boolean includeRuntime
+ ) {
+ FqName mainClass = null;
+ for (JetFile file : configuration.getEnvironment().getSourceFiles()) {
+ if (JetMainDetector.hasMain(file.getDeclarations())) {
+ FqName fqName = JetPsiUtil.getFQName(file);
+ mainClass = fqName.child(JvmAbi.PACKAGE_CLASS);
+ break;
+ }
+ }
+
+ CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getCompilerDependencies());
+
+ GenerationState generationState = analyzeAndGenerate(configuration);
+ if (generationState == null) {
+ return false;
+ }
+
+ ClassFileFactory factory = generationState.getFactory();
+ if (jar != null) {
+ try {
+ CompileEnvironmentUtil.writeToJar(factory, new FileOutputStream(jar), mainClass, includeRuntime);
+ } catch (FileNotFoundException e) {
+ throw new CompileEnvironmentException("Invalid jar path " + jar, e);
+ }
+ }
+ else if (outputDir != null) {
+ CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir);
+ }
+ else {
+ throw new CompileEnvironmentException("Output directory or jar file is not specified - no files will be saved to the disk");
+ }
+ return true;
+ }
+
+ public static boolean compileBunchOfSources(
+ CompileEnvironmentConfiguration configuration,
+
+ String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) {
+ configuration.getEnvironment().addSources(sourceFileOrDir);
+
+ return compileBunchOfSources(configuration, jar, outputDir, includeRuntime);
+ }
+
+ public static boolean compileBunchOfSourceDirectories(
+ CompileEnvironmentConfiguration configuration,
+
+ List sources, String jar, String outputDir, boolean includeRuntime) {
+ for (String source : sources) {
+ configuration.getEnvironment().addSources(source);
+ }
+
+ return compileBunchOfSources(configuration, jar, outputDir, includeRuntime);
+ }
+
+ @Nullable
+ public static ClassLoader compileText(
+ CompileEnvironmentConfiguration configuration,
+
+ String code) {
+ configuration.getEnvironment().addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code));
+
+ GenerationState generationState = analyzeAndGenerate(configuration);
+ if (generationState == null) {
+ return null;
+ }
+ return new GeneratedClassLoader(generationState.getFactory());
+ }
+
+ @Nullable
+ public static GenerationState analyzeAndGenerate(CompileEnvironmentConfiguration configuration) {
+ return analyzeAndGenerate(configuration, configuration.getCompilerDependencies().getCompilerSpecialMode().isStubs());
+ }
+
+ @Nullable
+ public static GenerationState analyzeAndGenerate(
+ CompileEnvironmentConfiguration configuration,
boolean stubs
) {
- AnalyzeExhaust exhaust = analyze(environment, dependencies, messageCollector, stubs);
+ AnalyzeExhaust exhaust = analyze(configuration, stubs);
if (exhaust == null) {
return null;
@@ -73,14 +235,13 @@ public class KotlinToJVMBytecodeCompiler {
exhaust.throwIfError();
- return generate(environment, dependencies, messageCollector, exhaust, stubs);
+ return generate(configuration, exhaust, stubs);
}
@Nullable
private static AnalyzeExhaust analyze(
- JetCoreEnvironment environment,
- CompilerDependencies dependencies,
- final MessageCollector messageCollector,
+ final CompileEnvironmentConfiguration configuration,
+
boolean stubs) {
final Ref hasErrors = new Ref(false);
final MessageCollector messageCollectorWrapper = new MessageCollector() {
@@ -92,10 +253,12 @@ public class KotlinToJVMBytecodeCompiler {
if (CompilerMessageSeverity.ERRORS.contains(severity)) {
hasErrors.set(true);
}
- messageCollector.report(severity, message, location);
+ configuration.getMessageCollector().report(severity, message, location);
}
};
+ JetCoreEnvironment environment = configuration.getEnvironment();
+
// Report syntax errors
for (JetFile file : environment.getSourceFiles()) {
file.accept(new PsiRecursiveElementWalkingVisitor() {
@@ -114,7 +277,7 @@ public class KotlinToJVMBytecodeCompiler {
stubs ? Predicates.alwaysFalse() : Predicates.alwaysTrue();
AnalyzeExhaust exhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely, JetControlFlowDataTraceFactory.EMPTY,
- dependencies);
+ configuration.getCompilerDependencies());
for (Diagnostic diagnostic : exhaust.getBindingContext().getDiagnostics()) {
reportDiagnostic(messageCollectorWrapper, diagnostic);
@@ -127,26 +290,24 @@ public class KotlinToJVMBytecodeCompiler {
@NotNull
private static GenerationState generate(
- JetCoreEnvironment environment,
- CompilerDependencies dependencies,
-
- final MessageCollector messageCollector,
+ final CompileEnvironmentConfiguration configuration,
AnalyzeExhaust exhaust,
boolean stubs) {
+ JetCoreEnvironment environment = configuration.getEnvironment();
Project project = environment.getProject();
Progress backendProgress = new Progress() {
@Override
public void log(String message) {
- messageCollector.report(CompilerMessageSeverity.LOGGING, message, CompilerMessageLocation.NO_LOCATION);
+ configuration.getMessageCollector().report(CompilerMessageSeverity.LOGGING, message, CompilerMessageLocation.NO_LOCATION);
}
};
GenerationState generationState = new GenerationState(project, ClassBuilderFactories.binaries(stubs), backendProgress,
- exhaust, environment.getSourceFiles(), dependencies.getCompilerSpecialMode());
+ exhaust, environment.getSourceFiles(), configuration.getCompilerDependencies().getCompilerSpecialMode());
generationState.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
- List plugins = environment.getCompilerPlugins();
+ List plugins = configuration.getCompilerPlugins();
if (plugins != null) {
CompilerPluginContext context = new CompilerPluginContext(project, exhaust.getBindingContext(), environment.getSourceFiles());
for (CompilerPlugin plugin : plugins) {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java
new file mode 100644
index 00000000000..03c5013330a
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolutionContext.java
@@ -0,0 +1,40 @@
+/*
+ * 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.jet.lang.resolve.calls;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
+import org.jetbrains.jet.lang.psi.Call;
+import org.jetbrains.jet.lang.resolve.BindingTrace;
+
+/**
+* @author svtk
+*/
+public final class CallResolutionContext extends ResolutionContext {
+ /*package*/ final ResolvedCallImpl candidateCall;
+ /*package*/ final TracingStrategy tracing;
+
+ public CallResolutionContext(@NotNull ResolvedCallImpl candidateCall, @NotNull ResolutionTask task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing, @NotNull Call call) {
+ super(trace, task.scope, call, task.expectedType, task.dataFlowInfo);
+ this.candidateCall = candidateCall;
+ this.tracing = tracing;
+ }
+
+ public CallResolutionContext(@NotNull ResolvedCallImpl candidateCall, @NotNull ResolutionTask task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
+ this(candidateCall, task, trace, tracing, task.call);
+ }
+}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
index 5b62fdadd2a..219f06d9156 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java
@@ -102,16 +102,16 @@ public class CallResolver {
if (referencedName == null) {
return OverloadResolutionResultsImpl.nameNotFound();
}
- TaskPrioritizer task_prioritizer;
+ List> memberPrioritizers = Lists.newArrayList();
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
referencedName = referencedName.substring(1);
- task_prioritizer = TaskPrioritizers.PROPERTY_TASK_PRIORITIZER;
+ memberPrioritizers.add(MemberPrioritizers.PROPERTY_TASK_PRIORITIZER);
}
else {
- task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER;
+ memberPrioritizers.add(MemberPrioritizers.VARIABLE_TASK_PRIORITIZER);
}
- List> prioritizedTasks = task_prioritizer.computePrioritizedTasks(context, referencedName, nameExpression);
- return doResolveCall(context, prioritizedTasks, nameExpression);
+ List> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, memberPrioritizers);
+ return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.PROPERTY_CALL_TRANSFORMATION_STRATEGY, nameExpression);
}
@NotNull
@@ -119,9 +119,9 @@ public class CallResolver {
@NotNull BasicResolutionContext context,
@NotNull final JetReferenceExpression functionReference,
@NotNull String name) {
- List> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(
- context, name, functionReference);
- return doResolveCall(context, tasks, functionReference);
+ List> tasks = TaskPrioritizer.computePrioritizedTasks(
+ context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
+ return doResolveCall(context, tasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
}
@NotNull
@@ -142,7 +142,7 @@ public class CallResolver {
String name = expression.getReferencedName();
if (name == null) return checkArgumentTypesAndFail(context);
- prioritizedTasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(context, name, functionReference);
+ prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
@Override
public boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
@@ -184,7 +184,7 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context);
}
- Collection> candidates = TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors);
+ Collection> candidates = TaskPrioritizer.convertWithImpliedThis(context.scope, Collections.singletonList(NO_RECEIVER), constructors);
prioritizedTasks.add(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
}
else {
@@ -206,7 +206,7 @@ public class CallResolver {
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
return checkArgumentTypesAndFail(context);
}
- List> candidates = ResolvedCallImpl.convertCollection(constructors);
+ List> candidates = ResolutionCandidate.convertCollection(constructors);
prioritizedTasks = Collections.singletonList(new ResolutionTask(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
}
else if (calleeExpression != null) {
@@ -223,15 +223,15 @@ public class CallResolver {
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
- ResolvedCallImpl resolvedCall = ResolvedCallImpl.create(functionDescriptor);
- resolvedCall.setReceiverArgument(context.call.getExplicitReceiver());
+ ResolutionCandidate resolutionCandidate = ResolutionCandidate.create(functionDescriptor);
+ resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
// strictly speaking, this is a hack:
// we need to pass a reference, but there's no reference in the PSI,
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
functionReference = new JetFakeReference(calleeExpression);
- prioritizedTasks = Collections.singletonList(new ResolutionTask(Collections.singleton(resolvedCall), functionReference, context));
+ prioritizedTasks = Collections.singletonList(new ResolutionTask(Collections.singleton(resolutionCandidate), functionReference, context));
}
else {
// checkTypesWithNoCallee(trace, scope, call);
@@ -239,7 +239,7 @@ public class CallResolver {
}
}
- return doResolveCall(context, prioritizedTasks, functionReference);
+ return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
}
private OverloadResolutionResults checkArgumentTypesAndFail(BasicResolutionContext context) {
@@ -251,6 +251,7 @@ public class CallResolver {
private OverloadResolutionResults doResolveCall(
@NotNull final BasicResolutionContext context,
@NotNull final List> prioritizedTasks, // high to low priority
+ @NotNull CallTransformationStrategy callTransformationStrategy,
@NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
@@ -267,7 +268,7 @@ public class CallResolver {
OverloadResolutionResultsImpl resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask task : prioritizedTasks) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
- OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace));
+ OverloadResolutionResultsImpl results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), callTransformationStrategy);
if (results.isSuccess() || results.isAmbiguity()) {
temporaryTrace.commit();
@@ -299,8 +300,9 @@ public class CallResolver {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
- private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(ResolutionTask task) {
- OverloadResolutionResultsImpl results = performResolution(task);
+ private OverloadResolutionResultsImpl performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask task,
+ @NotNull CallTransformationStrategy callTransformationStrategy) {
+ OverloadResolutionResultsImpl results = performResolution(task, callTransformationStrategy);
// If resolution fails, we should check for some of the following situations:
// class A {
@@ -323,9 +325,9 @@ public class CallResolver {
// We have some candidates that failed for some reason
// And we have a suspect: the function literal argument
// Now, we try to remove this argument and see if it helps
- Collection> newCandidates = Lists.newArrayList();
- for (ResolvedCallImpl candidate : task.getCandidates()) {
- newCandidates.add(ResolvedCallImpl.create(candidate.getCandidateDescriptor()));
+ Collection> newCandidates = Lists.newArrayList();
+ for (ResolutionCandidate candidate : task.getCandidates()) {
+ newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor()));
}
ResolutionTask newContext = new ResolutionTask(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) {
@NotNull
@@ -334,7 +336,7 @@ public class CallResolver {
return Collections.emptyList();
}
}, task.expectedType, task.dataFlowInfo);
- OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(newContext);
+ OverloadResolutionResultsImpl resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformationStrategy);
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
}
@@ -344,101 +346,23 @@ public class CallResolver {
}
@NotNull
- private OverloadResolutionResultsImpl performResolution(ResolutionTask task) {
- for (ResolvedCallImpl candidateCall : task.getCandidates()) {
- D candidate = candidateCall.getCandidateDescriptor();
+ private OverloadResolutionResultsImpl performResolution(@NotNull ResolutionTask task,
+ @NotNull CallTransformationStrategy callTransformationStrategy) {
+
+ for (ResolutionCandidate resolutionCandidate : task.getCandidates()) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace);
- candidateCall.setTrace(temporaryTrace);
+ CallResolutionContext context = callTransformationStrategy.createCallContext(resolutionCandidate, task, temporaryTrace, task.tracing);
+ performResolutionForCandidateCall(context, task, temporaryTrace);
- CallResolutionContext context = new CallResolutionContext(candidateCall, task, temporaryTrace, task.tracing);
-
- context.tracing.bindReference(context.trace, candidateCall);
-
- if (ErrorUtils.isError(candidate)) {
- candidateCall.setStatus(SUCCESS);
- checkTypesWithNoCallee(context.toBasic());
- continue;
+ Collection> calls = callTransformationStrategy.transformResultCall(context, this, task);
+ for (ResolvedCallImpl call : calls) {
+ task.getResolvedCallMap().put(resolutionCandidate, call);
}
-
- if (!Visibilities.isVisible(candidate, context.scope.getContainingDeclaration())) {
- candidateCall.setStatus(OTHER_ERROR);
- context.tracing.invisibleMember(context.trace, candidate);
- continue;
- }
-
- boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall);
- if (errorInArgumentMapping) {
- candidateCall.setStatus(OTHER_ERROR);
- checkTypesWithNoCallee(context.toBasic());
- continue;
- }
-
- List jetTypeArguments = context.call.getTypeArguments();
- if (jetTypeArguments.isEmpty()) {
- if (!candidate.getTypeParameters().isEmpty()) {
- candidateCall.setStatus(inferTypeArguments(context));
- }
- else {
- candidateCall.setStatus(checkAllValueArguments(context));
- }
- }
- else {
- // Explicit type arguments passed
-
- List typeArguments = new ArrayList();
- for (JetTypeProjection projection : jetTypeArguments) {
- if (projection.getProjectionKind() != JetProjectionKind.NONE) {
- context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
- }
- JetTypeReference typeReference = projection.getTypeReference();
- if (typeReference != null) {
- typeArguments.add(typeResolver.resolveType(context.scope, typeReference, context.trace, true));
- }
- else {
- typeArguments.add(ErrorUtils.createErrorType("Star projection in a call"));
- }
- }
- int expectedTypeArgumentCount = candidate.getTypeParameters().size();
- if (expectedTypeArgumentCount == jetTypeArguments.size()) {
-
- checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
-
- Map substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
- D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
-
- candidateCall.setResultingDescriptor(substitutedDescriptor);
- replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
-
- List typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
- for (int i = 0; i < typeParameters.size(); i++) {
- TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
- candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
- }
- candidateCall.setStatus(checkAllValueArguments(context));
- }
- else {
- candidateCall.setStatus(OTHER_ERROR);
- context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
- }
- }
-
- task.performAdvancedChecks(candidate, context.trace, context.tracing);
-
- // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
- // See TaskPrioritizer for more
- JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
- if (superExpression != null) {
- context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
- candidateCall.setStatus(OTHER_ERROR);
- }
-
- recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
- recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
}
Set> successfulCandidates = Sets.newLinkedHashSet();
Set> failedCandidates = Sets.newLinkedHashSet();
- for (ResolvedCallImpl candidateCall : task.getCandidates()) {
+ for (ResolvedCallImpl candidateCall : task.getResolvedCallMap().values()) {
ResolutionStatus status = candidateCall.getStatus();
if (status.isSuccess()) {
successfulCandidates.add(candidateCall);
@@ -456,6 +380,103 @@ public class CallResolver {
return results;
}
+ private void performResolutionForCandidateCall(@NotNull CallResolutionContext context,
+ @NotNull ResolutionTask task,
+ @NotNull TemporaryBindingTrace temporaryTrace) {
+ ResolvedCallImpl candidateCall = context.candidateCall;
+
+ candidateCall.setTrace(temporaryTrace);
+ D candidate = candidateCall.getCandidateDescriptor();
+
+ context.tracing.bindReference(context.trace, candidateCall);
+
+ if (ErrorUtils.isError(candidate)) {
+ candidateCall.addStatus(SUCCESS);
+ checkTypesWithNoCallee(context.toBasic());
+ return;
+ }
+
+ if (!Visibilities.isVisible(candidate, context.scope.getContainingDeclaration())) {
+ candidateCall.addStatus(OTHER_ERROR);
+ context.tracing.invisibleMember(context.trace, candidate);
+ return;
+ }
+
+ ValueArgumentsToParametersMapper.Status
+ argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing,
+ candidateCall);
+ if (!argumentMappingStatus.isSuccess()) {
+ candidateCall.addStatus(OTHER_ERROR);
+ if (argumentMappingStatus == ValueArgumentsToParametersMapper.Status.ERROR) {
+ checkTypesWithNoCallee(context.toBasic());
+ return;
+ }
+ }
+
+ List jetTypeArguments = context.call.getTypeArguments();
+ if (jetTypeArguments.isEmpty()) {
+ if (!candidate.getTypeParameters().isEmpty()) {
+ candidateCall.addStatus(inferTypeArguments(context));
+ }
+ else {
+ candidateCall.addStatus(checkAllValueArguments(context));
+ }
+ }
+ else {
+ // Explicit type arguments passed
+
+ List typeArguments = new ArrayList();
+ for (JetTypeProjection projection : jetTypeArguments) {
+ if (projection.getProjectionKind() != JetProjectionKind.NONE) {
+ context.trace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
+ }
+ JetTypeReference typeReference = projection.getTypeReference();
+ if (typeReference != null) {
+ typeArguments.add(typeResolver.resolveType(context.scope, typeReference, context.trace, true));
+ }
+ else {
+ typeArguments.add(ErrorUtils.createErrorType("Star projection in a call"));
+ }
+ }
+ int expectedTypeArgumentCount = candidate.getTypeParameters().size();
+ if (expectedTypeArgumentCount == jetTypeArguments.size()) {
+
+ checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, context.trace);
+
+ Map
+ substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor)candidate, typeArguments);
+ D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
+
+ candidateCall.setResultingDescriptor(substitutedDescriptor);
+ replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
+
+ List typeParameters = candidateCall.getCandidateDescriptor().getTypeParameters();
+ for (int i = 0; i < typeParameters.size(); i++) {
+ TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
+ candidateCall.recordTypeArgument(typeParameterDescriptor, typeArguments.get(i));
+ }
+ candidateCall.addStatus(checkAllValueArguments(context));
+ }
+ else {
+ candidateCall.addStatus(OTHER_ERROR);
+ context.tracing.wrongNumberOfTypeArguments(context.trace, expectedTypeArgumentCount);
+ }
+ }
+
+ task.performAdvancedChecks(candidate, context.trace, context.tracing);
+
+ // 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
+ // See TaskPrioritizer for more
+ JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
+ if (superExpression != null) {
+ context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
+ candidateCall.addStatus(OTHER_ERROR);
+ }
+
+ recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
+ recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
+ }
+
private ResolutionStatus inferTypeArguments(CallResolutionContext context) {
ResolvedCallImpl candidateCall = context.candidateCall;
D candidate = candidateCall.getCandidateDescriptor();
@@ -843,25 +864,26 @@ public class CallResolver {
@NotNull
public OverloadResolutionResults resolveExactSignature(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List parameterTypes) {
- List> result = findCandidatesByExactSignature(scope, receiver, name, parameterTypes);
+ List> candidates = findCandidatesByExactSignature(scope, receiver, name, parameterTypes);
BindingTraceContext trace = new BindingTraceContext();
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
- Set> candidates = Sets.newLinkedHashSet();
- for (ResolvedCallImpl call : result) {
+ Set> calls = Sets.newLinkedHashSet();
+ for (ResolutionCandidate candidate : candidates) {
+ ResolvedCallImpl call = ResolvedCallImpl.create(candidate);
call.setTrace(temporaryBindingTrace);
- candidates.add(call);
+ calls.add(call);
}
- return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, candidates, Collections.>emptySet());
+ return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.>emptySet());
}
- private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
+ private List> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
String name, List parameterTypes) {
- List> result = Lists.newArrayList();
+ List> result = Lists.newArrayList();
if (receiver.exists()) {
- Collection> extensionFunctionDescriptors = ResolvedCallImpl.convertCollection(scope.getFunctions(name));
- List> nonlocal = Lists.newArrayList();
- List> local = Lists.newArrayList();
+ Collection> extensionFunctionDescriptors = ResolutionCandidate.convertCollection(scope.getFunctions(name));
+ List> nonlocal = Lists.newArrayList();
+ List> local = Lists.newArrayList();
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
@@ -869,7 +891,7 @@ public class CallResolver {
return result;
}
- Collection> functionDescriptors = ResolvedCallImpl.convertCollection(receiver.getType().getMemberScope().getFunctions(name));
+ Collection> functionDescriptors = ResolutionCandidate.convertCollection(receiver.getType().getMemberScope().getFunctions(name));
if (lookupExactSignature(functionDescriptors, parameterTypes, result)) {
return result;
@@ -878,16 +900,16 @@ public class CallResolver {
return result;
}
else {
- lookupExactSignature(ResolvedCallImpl.convertCollection(scope.getFunctions(name)), parameterTypes, result);
+ lookupExactSignature(ResolutionCandidate.convertCollection(scope.getFunctions(name)), parameterTypes, result);
return result;
}
}
- private static boolean lookupExactSignature(Collection> candidates, List parameterTypes,
- List> result) {
+ private static boolean lookupExactSignature(Collection> candidates, List parameterTypes,
+ List> result) {
boolean found = false;
- for (ResolvedCallImpl resolvedCall : candidates) {
- FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
+ for (ResolutionCandidate resolvedCall : candidates) {
+ FunctionDescriptor functionDescriptor = resolvedCall.getDescriptor();
if (functionDescriptor.getReceiverParameter().exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
@@ -897,17 +919,17 @@ public class CallResolver {
return found;
}
- private boolean findExtensionFunctions(Collection> candidates, ReceiverDescriptor receiver,
- List parameterTypes, List> result) {
+ private boolean findExtensionFunctions(Collection> candidates, ReceiverDescriptor receiver,
+ List parameterTypes, List> result) {
boolean found = false;
- for (ResolvedCallImpl resolvedCall : candidates) {
- FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
+ for (ResolutionCandidate candidate : candidates) {
+ FunctionDescriptor functionDescriptor = candidate.getDescriptor();
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiverParameter();
if (!functionReceiver.exists()) continue;
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
if (!typeChecker.isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
if (!checkValueParameters(functionDescriptor, parameterTypes))continue;
- result.add(resolvedCall);
+ result.add(candidate);
found = true;
}
return found;
@@ -923,15 +945,4 @@ public class CallResolver {
}
return true;
}
-
- private static final class CallResolutionContext extends ResolutionContext {
- /*package*/ final ResolvedCallImpl candidateCall;
- /*package*/ final TracingStrategy tracing;
-
- public CallResolutionContext(ResolvedCallImpl candidateCall, ResolutionTask task, BindingTrace trace, TracingStrategy tracing) {
- super(trace, task.scope, task.call, task.expectedType, task.dataFlowInfo);
- this.candidateCall = candidateCall;
- this.tracing = tracing;
- }
- }
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java
new file mode 100644
index 00000000000..5fc68364ae5
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformationStrategy.java
@@ -0,0 +1,118 @@
+/*
+ * 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.jet.lang.resolve.calls;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
+import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
+import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
+import org.jetbrains.jet.lang.psi.*;
+import org.jetbrains.jet.lang.resolve.BindingTrace;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author svtk
+ */
+public interface CallTransformationStrategy {
+
+ @NotNull
+ CallResolutionContext createCallContext(@NotNull ResolutionCandidate candidate,
+ @NotNull ResolutionTask task,
+ @NotNull BindingTrace trace,
+ @NotNull TracingStrategy tracing);
+
+ @NotNull
+ Collection> transformResultCall(@NotNull CallResolutionContext callResolutionContext,
+ @NotNull CallResolver callResolver,
+ @NotNull ResolutionTask task);
+
+ CallTransformationStrategy
+ PROPERTY_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy() {
+ @NotNull
+ @Override
+ public CallResolutionContext createCallContext(@NotNull ResolutionCandidate candidate,
+ @NotNull ResolutionTask task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
+ ResolvedCallImpl candidateCall = ResolvedCallImpl.create(candidate);
+ return new CallResolutionContext(candidateCall, task, trace, tracing);
+ }
+
+ @NotNull
+ @Override
+ public Collection> transformResultCall(@NotNull CallResolutionContext context,
+ @NotNull CallResolver callResolver, @NotNull ResolutionTask task) {
+ return Collections.singleton(context.candidateCall);
+ }
+ };
+
+ CallTransformationStrategy
+ FUNCTION_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy() {
+ @NotNull
+ @Override
+ public CallResolutionContext createCallContext(@NotNull ResolutionCandidate candidate,
+ @NotNull ResolutionTask task,
+ @NotNull BindingTrace trace,
+ @NotNull TracingStrategy tracing) {
+ if (candidate.getDescriptor() instanceof FunctionDescriptor) {
+ return new CallResolutionContext(ResolvedCallImpl.create(candidate), task, trace, tracing);
+ }
+ assert candidate.getDescriptor() instanceof VariableDescriptor;
+ Call propertyCall = new DelegatingCall(task.call) {
+ @Override
+ public JetValueArgumentList getValueArgumentList() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public List getFunctionLiteralArguments() {
+ return Collections.emptyList();
+ }
+
+ @NotNull
+ @Override
+ public List getTypeArguments() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public JetTypeArgumentList getTypeArgumentList() {
+ return null;
+ }
+ };
+ return new CallResolutionContext(ResolvedCallImpl.create(candidate), task, trace, tracing, propertyCall);
+ }
+
+ @NotNull
+ @Override
+ public Collection> transformResultCall(@NotNull CallResolutionContext context,
+ @NotNull CallResolver callResolver, @NotNull ResolutionTask task) {
+ FunctionDescriptor descriptor = context.candidateCall.getCandidateDescriptor();
+ if (descriptor instanceof FunctionDescriptor) {
+ return Collections.singleton(context.candidateCall);
+ }
+ assert descriptor instanceof VariableDescriptor;
+ BasicResolutionContext basicResolutionContext =
+ BasicResolutionContext.create(context.trace, context.scope, task.call, context.expectedType, context.dataFlowInfo);
+ OverloadResolutionResults results =
+ callResolver.resolveCallWithGivenName(basicResolutionContext, task.reference, "invoke");
+ return ((OverloadResolutionResultsImpl)results).getResultingCalls();
+ }
+ };
+}
diff --git a/confluence/src/main/java/com/intellij/psi/tree/TokenSet.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java
similarity index 50%
rename from confluence/src/main/java/com/intellij/psi/tree/TokenSet.java
rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java
index aa29a84d471..14dace99c4d 100644
--- a/confluence/src/main/java/com/intellij/psi/tree/TokenSet.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizer.java
@@ -14,27 +14,25 @@
* limitations under the License.
*/
-package com.intellij.psi.tree;
+package org.jetbrains.jet.lang.resolve.calls;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
+import org.jetbrains.jet.lang.resolve.scopes.JetScope;
+import org.jetbrains.jet.lang.types.JetType;
+
+import java.util.Collection;
/**
- * @author abreslav
+ * @author svtk
*/
-public class TokenSet {
- public static TokenSet create(IElementType... tokens) {
- return new TokenSet(tokens);
- }
+public interface MemberPrioritizer {
+ @NotNull
+ Collection getNonExtensionsByName(JetScope scope, String name);
- private final Set tokens = new HashSet();
+ @NotNull
+ Collection getMembersByName(@NotNull JetType receiver, String name);
- public TokenSet(IElementType... tokens) {
- this.tokens.addAll(Arrays.asList(tokens));
- }
-
- public Set asSet() {
- return tokens;
- }
+ @NotNull
+ Collection getExtensionsByName(JetScope scope, String name);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizers.java
similarity index 82%
rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java
rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizers.java
index 48e16fb27c1..a7e793dcb4a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizers.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/MemberPrioritizers.java
@@ -34,14 +34,15 @@ import java.util.*;
/**
* @author abreslav
*/
-public class TaskPrioritizers {
+public class MemberPrioritizers {
- /*package*/ static TaskPrioritizer FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer() {
+ /*package*/ static MemberPrioritizer FUNCTION_TASK_PRIORITIZER = new MemberPrioritizer() {
+
@NotNull
@Override
- protected Collection getNonExtensionsByName(JetScope scope, String name) {
+ public Collection getNonExtensionsByName(JetScope scope, String name) {
Set functions = Sets.newLinkedHashSet(scope.getFunctions(name));
for (Iterator iterator = functions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
@@ -57,7 +58,7 @@ public class TaskPrioritizers {
@NotNull
@Override
- protected Collection getMembersByName(@NotNull JetType receiverType, String name) {
+ public Collection getMembersByName(@NotNull JetType receiverType, String name) {
JetScope receiverScope = receiverType.getMemberScope();
Set members = Sets.newHashSet(receiverScope.getFunctions(name));
addConstructors(receiverScope, name, members);
@@ -67,7 +68,7 @@ public class TaskPrioritizers {
@NotNull
@Override
- protected Collection getExtensionsByName(JetScope scope, String name) {
+ public Collection getExtensionsByName(JetScope scope, String name) {
Set extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
for (Iterator iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
FunctionDescriptor descriptor = iterator.next();
@@ -104,11 +105,11 @@ public class TaskPrioritizers {
}
};
- /*package*/ static TaskPrioritizer VARIABLE_TASK_PRIORITIZER = new TaskPrioritizer() {
+ /*package*/ static MemberPrioritizer VARIABLE_TASK_PRIORITIZER = new MemberPrioritizer() {
@NotNull
@Override
- protected Collection getNonExtensionsByName(JetScope scope, String name) {
+ public Collection getNonExtensionsByName(JetScope scope, String name) {
VariableDescriptor descriptor = scope.getLocalVariable(name);
if (descriptor == null) {
descriptor = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name));
@@ -119,13 +120,13 @@ public class TaskPrioritizers {
@NotNull
@Override
- protected Collection getMembersByName(@NotNull JetType receiverType, String name) {
+ public Collection getMembersByName(@NotNull JetType receiverType, String name) {
return receiverType.getMemberScope().getProperties(name);
}
@NotNull
@Override
- protected Collection getExtensionsByName(JetScope scope, String name) {
+ public Collection getExtensionsByName(JetScope scope, String name) {
return Collections2.filter(scope.getProperties(name), new Predicate() {
@Override
public boolean apply(@Nullable VariableDescriptor variableDescriptor) {
@@ -135,7 +136,7 @@ public class TaskPrioritizers {
}
};
- /*package*/ static TaskPrioritizer PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer() {
+ /*package*/ static MemberPrioritizer PROPERTY_TASK_PRIORITIZER = new MemberPrioritizer() {
private Collection filterProperties(Collection extends VariableDescriptor> variableDescriptors) {
ArrayList properties = Lists.newArrayList();
for (VariableDescriptor descriptor : variableDescriptors) {
@@ -148,19 +149,19 @@ public class TaskPrioritizers {
@NotNull
@Override
- protected Collection getNonExtensionsByName(JetScope scope, String name) {
+ public Collection getNonExtensionsByName(JetScope scope, String name) {
return filterProperties(VARIABLE_TASK_PRIORITIZER.getNonExtensionsByName(scope, name));
}
@NotNull
@Override
- protected Collection getMembersByName(@NotNull JetType receiver, String name) {
+ public Collection getMembersByName(@NotNull JetType receiver, String name) {
return filterProperties(VARIABLE_TASK_PRIORITIZER.getMembersByName(receiver, name));
}
@NotNull
@Override
- protected Collection getExtensionsByName(JetScope scope, String name) {
+ public Collection getExtensionsByName(JetScope scope, String name) {
return filterProperties(VARIABLE_TASK_PRIORITIZER.getExtensionsByName(scope, name));
}
};
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java
index 44c37c97435..1edce3205fa 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java
@@ -25,10 +25,10 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
-import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
-import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
+import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
+import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.List;
import java.util.Set;
@@ -95,29 +95,73 @@ public class OverloadingConflictResolver {
int fSize = fParams.size();
int gSize = gParams.size();
- if (fSize > gSize) return false;
- for (int i = 0; i < gSize; i++) {
- ValueParameterDescriptor gParam = gParams.get(i);
- JetType gParamType = gParam.getType();
- if (i >= fSize) {
- // f() has fewer parameters than g()
- // The point is: g() may have a last vararg that doesn't get any arguments
- // In this case f() is more specific, because one can explicitly pass
- // an empty array to g() and make it preferred
- if (i != gSize - 1 || gParam.getVarargElementType() == null) {
+ boolean fIsVararg = isVariableArity(fParams);
+ boolean gIsVararg = isVariableArity(gParams);
+
+ if (!fIsVararg && gIsVararg) return true;
+ if (fIsVararg && !gIsVararg) return false;
+
+ if (!fIsVararg && !gIsVararg) {
+ if (fSize != gSize) return false;
+
+ for (int i = 0; i < fSize; i++) {
+ ValueParameterDescriptor fParam = fParams.get(i);
+ ValueParameterDescriptor gParam = gParams.get(i);
+
+ JetType fParamType = fParam.getType();
+ JetType gParamType = gParam.getType();
+
+ if (!typeMoreSpecific(fParamType, gParamType)) {
return false;
}
- return true;
- }
-
- JetType fParamType = fParams.get(i).getType();
-
- if (!typeMoreSpecific(fParamType, gParamType)) {
- return false;
}
}
-
+
+ if (fIsVararg && gIsVararg) {
+ // Check matching parameters
+ int minSize = Math.min(fSize, gSize);
+ for (int i = 0; i < minSize - 1; i++) {
+ ValueParameterDescriptor fParam = fParams.get(i);
+ ValueParameterDescriptor gParam = gParams.get(i);
+
+ JetType fParamType = fParam.getType();
+ JetType gParamType = gParam.getType();
+
+ if (!typeMoreSpecific(fParamType, gParamType)) {
+ return false;
+ }
+ }
+
+ // Check the non-matching parameters of one function against the vararg parameter of the other funciton
+ // Example:
+ // f(a : A, vararg vf : T)
+ // g(vararg vg : T)
+ // here we check that typeof(a) < typeof(vg) and elementTypeOf(vf) < elementTypeOf(vg)
+ if (fSize < gSize) {
+ ValueParameterDescriptor fParam = fParams.get(fSize - 1);
+ JetType fParamType = fParam.getVarargElementType();
+ assert fParamType != null : "fIsVararg guarantees this";
+ for (int i = fSize - 1; i < gSize; i++) {
+ ValueParameterDescriptor gParam = gParams.get(i);
+ if (!typeMoreSpecific(fParamType, gParam.getType())) {
+ return false;
+ }
+ }
+ }
+ else {
+ ValueParameterDescriptor gParam = gParams.get(gSize - 1);
+ JetType gParamType = gParam.getVarargElementType();
+ assert gParamType != null : "gIsVararg guarantees this";
+ for (int i = gSize - 1; i < fSize; i++) {
+ ValueParameterDescriptor fParam = fParams.get(i);
+ if (!typeMoreSpecific(fParam.getType(), gParamType)) {
+ return false;
+ }
+ }
+ }
+ }
+
if (discriminateGenericDescriptors && isGeneric(f)) {
if (!isGeneric(g)) {
return false;
@@ -130,7 +174,12 @@ public class OverloadingConflictResolver {
return true;
}
-
+
+ private boolean isVariableArity(List fParams) {
+ int fSize = fParams.size();
+ return fSize > 0 && fParams.get(fSize - 1).getVarargElementType() != null;
+ }
+
private boolean isGeneric(CallableDescriptor f) {
return !f.getOriginal().getTypeParameters().isEmpty();
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java
new file mode 100644
index 00000000000..829185e3e31
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionCandidate.java
@@ -0,0 +1,77 @@
+/*
+ * 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.jet.lang.resolve.calls;
+
+import com.google.common.collect.Lists;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
+import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
+
+import java.util.Collection;
+import java.util.List;
+
+import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
+
+/**
+ * @author svtk
+ */
+public class ResolutionCandidate {
+ private final D candidateDescriptor;
+ private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
+ private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
+
+ private ResolutionCandidate(@NotNull D descriptor) {
+ candidateDescriptor = descriptor;
+ }
+
+ public static ResolutionCandidate create(@NotNull D descriptor) {
+ return new ResolutionCandidate(descriptor);
+ }
+
+ public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
+ this.thisObject = thisObject;
+ }
+
+ public void setReceiverArgument(@NotNull ReceiverDescriptor receiverArgument) {
+ this.receiverArgument = receiverArgument;
+ }
+
+ @NotNull
+ public D getDescriptor() {
+ return candidateDescriptor;
+ }
+
+ @NotNull
+ public ReceiverDescriptor getThisObject() {
+ return thisObject;
+ }
+
+ @NotNull
+ public ReceiverDescriptor getReceiverArgument() {
+ return receiverArgument;
+ }
+
+ @NotNull
+ public static List> convertCollection(@NotNull Collection extends D> descriptors) {
+ List> result = Lists.newArrayList();
+ for (D descriptor : descriptors) {
+ result.add(create(descriptor));
+ }
+ return result;
+ }
+
+}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionStatus.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionStatus.java
index 5e53fbb25aa..d1584abad00 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionStatus.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionStatus.java
@@ -49,7 +49,7 @@ public enum ResolutionStatus {
}
public ResolutionStatus combine(ResolutionStatus other) {
- if (this.isSuccess()) return other;
+ if (this == UNKNOWN_STATUS || this.isSuccess()) return other;
if (!other.isSuccess() && this.getSeverityIndex() < other.getSeverityIndex()) return other;
return this;
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java
index 32f3873ee83..3f7468a0479 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java
@@ -16,6 +16,8 @@
package org.jetbrains.jet.lang.resolve.calls;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
@@ -39,10 +41,7 @@ import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
-import static org.jetbrains.jet.lang.diagnostics.Errors.DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED;
-import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
-import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
-import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
+import static org.jetbrains.jet.lang.resolve.BindingContext.*;
/**
* Stores candidates for call resolution.
@@ -50,26 +49,32 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
* @author abreslav
*/
public class ResolutionTask extends ResolutionContext {
- private final Collection> candidates;
+ private final Collection> candidates;
+ private final Multimap