Merge branch 'master' of github.com:JetBrains/kotlin
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ patches-master
|
|||||||
out
|
out
|
||||||
dist
|
dist
|
||||||
ideaSDK
|
ideaSDK
|
||||||
PluginVerifier
|
dependencies
|
||||||
.idea/dictionaries/yozh.xml
|
.idea/dictionaries/yozh.xml
|
||||||
.idea/workspace.xml
|
.idea/workspace.xml
|
||||||
tmp
|
tmp
|
||||||
|
|||||||
Generated
+1
-1
@@ -171,7 +171,7 @@
|
|||||||
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
|
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
|
||||||
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
|
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
|
||||||
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
|
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
|
||||||
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
|
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
|
||||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||||
|
|||||||
Generated
-1
@@ -1,7 +1,6 @@
|
|||||||
<component name="libraryTable">
|
<component name="libraryTable">
|
||||||
<library name="js-libs">
|
<library name="js-libs">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/args4j-2.0.12.jar!/" />
|
|
||||||
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/json.jar!/" />
|
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/json.jar!/" />
|
||||||
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R3.jar!/" />
|
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R3.jar!/" />
|
||||||
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/dart-r3300.jar!/" />
|
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/dart-r3300.jar!/" />
|
||||||
|
|||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Integration Tests" type="JUnit" factoryName="JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea">
|
||||||
|
<pattern>
|
||||||
|
<option name="PATTERN" value="org.jetbrains.jet.*" />
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
</pattern>
|
||||||
|
</extension>
|
||||||
|
<module name="compiler-integration-tests" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH" value="" />
|
||||||
|
<option name="PACKAGE_NAME" value="org.jetbrains.kotlin" />
|
||||||
|
<option name="MAIN_CLASS_NAME" value="" />
|
||||||
|
<option name="METHOD_NAME" value="" />
|
||||||
|
<option name="TEST_OBJECT" value="package" />
|
||||||
|
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx350m -XX:MaxPermSize=320m" />
|
||||||
|
<option name="PARAMETERS" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
|
<value defaultName="moduleWithDependencies" />
|
||||||
|
</option>
|
||||||
|
<envs />
|
||||||
|
<patterns />
|
||||||
|
<RunnerSettings RunnerId="Profile ">
|
||||||
|
<option name="myExternalizedOptions" value=" additional-options2=onexit\=snapshot " />
|
||||||
|
</RunnerSettings>
|
||||||
|
<RunnerSettings RunnerId="Run" />
|
||||||
|
<ConfigurationWrapper RunnerId="Run" />
|
||||||
|
<method />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
+2
-2
@@ -10,11 +10,11 @@
|
|||||||
<property name="plugin.xml.bk" value="${plugin.xml}.bk"/>
|
<property name="plugin.xml.bk" value="${plugin.xml}.bk"/>
|
||||||
<property name="plugin.xml.versioned" value="${plugin.xml}.versioned" />
|
<property name="plugin.xml.versioned" value="${plugin.xml}.versioned" />
|
||||||
|
|
||||||
<property name="compiler.version.java" value="compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompilerVersion.java"/>
|
<property name="compiler.version.java" value="compiler/cli/src/org/jetbrains/jet/cli/common/CompilerVersion.java"/>
|
||||||
<property name="compiler.version.java.bk" value="${compiler.version.java}.bk"/>
|
<property name="compiler.version.java.bk" value="${compiler.version.java}.bk"/>
|
||||||
<property name="compiler.version.java.versioned" value="${compiler.version.java}.versioned" />
|
<property name="compiler.version.java.versioned" value="${compiler.version.java}.versioned" />
|
||||||
|
|
||||||
<property name="plugin.verifier" value="${basedir}/PluginVerifier/plugin-verifier-1.0-SNAPSHOT.jar"/>
|
<property name="plugin.verifier" value="${basedir}/dependencies/plugin-verifier.jar"/>
|
||||||
<property name="plugin.zip" value="${artifact.output.path}/kotlin-plugin-${build.number}.zip" />
|
<property name="plugin.zip" value="${artifact.output.path}/kotlin-plugin-${build.number}.zip" />
|
||||||
|
|
||||||
<macrodef name="echoprop">
|
<macrodef name="echoprop">
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ classpath="$classpath:$root/out/production/stdlib"
|
|||||||
classpath="$classpath:$root/lib/*:$ideaRoot/lib/*:$ideaRoot/lib/rt/*"
|
classpath="$classpath:$root/lib/*:$ideaRoot/lib/*:$ideaRoot/lib/rt/*"
|
||||||
|
|
||||||
exec java $JAVA_OPTS \
|
exec java $JAVA_OPTS \
|
||||||
|
-ea \
|
||||||
-classpath "$classpath" \
|
-classpath "$classpath" \
|
||||||
org.jetbrains.jet.cli.jvm.K2JVMCompiler \
|
org.jetbrains.jet.cli.jvm.K2JVMCompiler \
|
||||||
"$@"
|
"$@"
|
||||||
|
|||||||
@@ -42,17 +42,18 @@ public class BytecodeCompiler {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new instance of {@link org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentConfiguration} instance using the arguments specified.
|
* Creates new instance of {@link org.jetbrains.jet.cli.jvm.compiler.K2JVMCompileEnvironmentConfiguration} instance using the arguments specified.
|
||||||
*
|
*
|
||||||
* @param stdlib path to "kotlin-runtime.jar", only used if not null and not empty
|
* @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
|
* @param classpath compilation classpath, only used if not null and not empty
|
||||||
*
|
*
|
||||||
* @return compile environment instance
|
* @return compile environment instance
|
||||||
*/
|
*/
|
||||||
private CompileEnvironmentConfiguration env( String stdlib, String[] classpath ) {
|
private K2JVMCompileEnvironmentConfiguration env( String stdlib, String[] classpath ) {
|
||||||
CompilerDependencies dependencies = CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR);
|
CompilerDependencies dependencies = CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR);
|
||||||
JetCoreEnvironment environment = new JetCoreEnvironment(CompileEnvironmentUtil.createMockDisposable(), dependencies);
|
JetCoreEnvironment environment = new JetCoreEnvironment(CompileEnvironmentUtil.createMockDisposable(), dependencies);
|
||||||
CompileEnvironmentConfiguration env = new CompileEnvironmentConfiguration(environment, dependencies, MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR);
|
K2JVMCompileEnvironmentConfiguration
|
||||||
|
env = new K2JVMCompileEnvironmentConfiguration(environment, MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR);
|
||||||
|
|
||||||
if (( stdlib != null ) && ( stdlib.trim().length() > 0 )) {
|
if (( stdlib != null ) && ( stdlib.trim().length() > 0 )) {
|
||||||
File file = new File(stdlib);
|
File file = new File(stdlib);
|
||||||
@@ -140,7 +141,7 @@ public class BytecodeCompiler {
|
|||||||
*/
|
*/
|
||||||
public void moduleToJar ( @NotNull String module, @NotNull String jar, boolean includeRuntime, @Nullable String stdlib, @Nullable String[] classpath ) {
|
public void moduleToJar ( @NotNull String module, @NotNull String jar, boolean includeRuntime, @Nullable String stdlib, @Nullable String[] classpath ) {
|
||||||
try {
|
try {
|
||||||
CompileEnvironmentConfiguration env = env(stdlib, classpath);
|
K2JVMCompileEnvironmentConfiguration env = env(stdlib, classpath);
|
||||||
List<Module> modules = CompileEnvironmentUtil.loadModuleScript(module, env.getMessageCollector());
|
List<Module> modules = CompileEnvironmentUtil.loadModuleScript(module, env.getMessageCollector());
|
||||||
File directory = new File(module).getParentFile();
|
File directory = new File(module).getParentFile();
|
||||||
boolean success = KotlinToJVMBytecodeCompiler.compileModules(env, modules, directory, jar, null, includeRuntime);
|
boolean success = KotlinToJVMBytecodeCompiler.compileModules(env, modules, directory, jar, null, includeRuntime);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<pathelement path="${idea.sdk}/lib/resources_en.jar"/>
|
<pathelement path="${idea.sdk}/lib/resources_en.jar"/>
|
||||||
|
|
||||||
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
|
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
|
||||||
|
<fileset dir="${basedir}/js/js.translator/lib" includes="*.jar"/>
|
||||||
<pathelement path="${output}/classes/runtime"/>
|
<pathelement path="${output}/classes/runtime"/>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
@@ -36,6 +37,9 @@
|
|||||||
<include name="util/src"/>
|
<include name="util/src"/>
|
||||||
<include name="jet.as.java.psi/src"/>
|
<include name="jet.as.java.psi/src"/>
|
||||||
</dirset>
|
</dirset>
|
||||||
|
<dirset dir="${basedir}/js/js.translator">
|
||||||
|
<include name="src"/>
|
||||||
|
</dirset>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<target name="init" depends="clean">
|
<target name="init" depends="clean">
|
||||||
@@ -166,17 +170,40 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="jarjar">
|
<target name="jarjar">
|
||||||
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${basedir}/build/jarjar-1.2.jar"/>
|
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${basedir}/dependencies/jarjar.jar"/>
|
||||||
|
<taskdef resource="proguard/ant/task.properties" classpath="${basedir}/dependencies/proguard.jar"/>
|
||||||
|
|
||||||
<jarjar jarfile="${output}/kotlin-compiler-tmp.jar">
|
<!-- JarJar Kotlin compiler & dependencies -->
|
||||||
|
<delete file="${output}/kotlin-compiler-jarjar.jar" failonerror="false"/>
|
||||||
|
<jarjar jarfile="${output}/kotlin-compiler-jarjar.jar">
|
||||||
<fileset dir="${output}/classes/compiler"/>
|
<fileset dir="${output}/classes/compiler"/>
|
||||||
<fileset dir="${output}/classes/runtime"/>
|
<fileset dir="${output}/classes/runtime"/>
|
||||||
<fileset dir="${basedir}/compiler/frontend/src" includes="jet/**"/>
|
<fileset dir="${basedir}/compiler/frontend/src" includes="jet/**"/>
|
||||||
|
|
||||||
<zipgroupfileset dir="${basedir}/lib" includes="*.jar"/>
|
<zipgroupfileset dir="${basedir}/lib" includes="*.jar"/>
|
||||||
<zipgroupfileset dir="${basedir}/ideaSDK/core" includes="*.jar"/>
|
<zipgroupfileset dir="${basedir}/ideaSDK/core" includes="*.jar"/>
|
||||||
|
<zipgroupfileset dir="${basedir}/js/js.translator/lib" includes="*.jar"/>
|
||||||
|
|
||||||
|
<zap pattern="com.thoughtworks.xstream.converters.extended.ISO8601*"/>
|
||||||
|
<zap pattern="com.thoughtworks.xstream.converters.reflection.CGLIBEnhancedConverter*"/>
|
||||||
|
<zap pattern="com.thoughtworks.xstream.io.xml.Dom4J*"/>
|
||||||
|
<zap pattern="com.thoughtworks.xstream.io.xml.Xom*"/>
|
||||||
|
<zap pattern="com.thoughtworks.xstream.mapper.CGLIBMapper*"/>
|
||||||
|
|
||||||
|
<zap pattern="org.apache.log4j.jmx.Agent"/>
|
||||||
|
<zap pattern="org.apache.log4j.net.JMS*"/>
|
||||||
|
<zap pattern="org.apache.log4j.net.SMTP*"/>
|
||||||
|
<zap pattern="org.apache.log4j.or.jms.MessageRenderer"/>
|
||||||
|
|
||||||
|
<zap pattern="org.jdom.xpath.Jaxen*"/>
|
||||||
|
|
||||||
|
<zap pattern="org.mozilla.javascript.xml.impl.xmlbeans.**" />
|
||||||
|
|
||||||
<rule pattern="com.intellij.**" result="kotlinc.internal.com.intellij.@1"/>
|
<rule pattern="com.intellij.**" result="kotlinc.internal.com.intellij.@1"/>
|
||||||
|
<rule pattern="com.sun.jna.**" result="kotlinc.internal.com.sun.jna.@1"/>
|
||||||
|
<rule pattern="org.apache.log4j.**" result="kotlinc.internal.org.apache.log4j.@1"/>
|
||||||
|
<rule pattern="org.jdom.**" result="kotlinc.internal.org.jdom.@1"/>
|
||||||
|
<rule pattern="JDOMAbout**" result="kotlinc.internal.org.jdom.JDOMAbout@1"/>
|
||||||
<rule pattern="org.intellij.lang.annotations.**" result="kotlinc.internal.org.intellij.lang.annotations.@1"/>
|
<rule pattern="org.intellij.lang.annotations.**" result="kotlinc.internal.org.intellij.lang.annotations.@1"/>
|
||||||
<rule pattern="org.jetbrains.annotations.**" result="kotlinc.internal.org.jetbrains.annotations.@1"/>
|
<rule pattern="org.jetbrains.annotations.**" result="kotlinc.internal.org.jetbrains.annotations.@1"/>
|
||||||
<rule pattern="com.google.**" result="kotlinc.internal.com.google.@1"/>
|
<rule pattern="com.google.**" result="kotlinc.internal.com.google.@1"/>
|
||||||
@@ -189,11 +216,13 @@
|
|||||||
|
|
||||||
<delete failonerror="false" dir="${output}/kotlin-compiler.exploded"/>
|
<delete failonerror="false" dir="${output}/kotlin-compiler.exploded"/>
|
||||||
<mkdir dir="${output}/kotlin-compiler.exploded"/>
|
<mkdir dir="${output}/kotlin-compiler.exploded"/>
|
||||||
|
<unzip src="${output}/kotlin-compiler-jarjar.jar" dest="${output}/kotlin-compiler.exploded"/>
|
||||||
|
|
||||||
<unzip src="${output}/kotlin-compiler-tmp.jar" dest="${output}/kotlin-compiler.exploded"/>
|
<delete file="${output}/kotlin-compiler-jarjar.jar"/>
|
||||||
<delete file="${output}/kotlin-compiler-tmp.jar"/>
|
|
||||||
|
|
||||||
<jar jarfile="${output}/kotlin-compiler-standalone.jar">
|
<!-- Clean JarJar result -->
|
||||||
|
<delete file="${output}/kotlin-compiler-clean.jar" failonerror="false"/>
|
||||||
|
<jar jarfile="${output}/kotlin-compiler-clean.jar">
|
||||||
<fileset dir="${output}/kotlin-compiler.exploded">
|
<fileset dir="${output}/kotlin-compiler.exploded">
|
||||||
<include name="**/*.class"/>
|
<include name="**/*.class"/>
|
||||||
<include name="**/*.jet"/>
|
<include name="**/*.jet"/>
|
||||||
@@ -213,8 +242,61 @@
|
|||||||
<attribute name="Main-Class" value="org.jetbrains.jet.cli.jvm.K2JVMCompiler"/>
|
<attribute name="Main-Class" value="org.jetbrains.jet.cli.jvm.K2JVMCompiler"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
</jar>
|
</jar>
|
||||||
|
|
||||||
<delete dir="${output}/kotlin-compiler.exploded" />
|
<delete dir="${output}/kotlin-compiler.exploded" />
|
||||||
|
|
||||||
|
<available property="rtjar" value="${java.home}/lib/rt.jar" file="${java.home}/lib/rt.jar" />
|
||||||
|
<available property="rtjar" value="${java.home}/../Classes/classes.jar" file="${java.home}/../Classes/classes.jar" />
|
||||||
|
|
||||||
|
<delete file="${output}/kotlin-compiler.jar" failonerror="false"/>
|
||||||
|
<proguard><![CDATA[
|
||||||
|
-injars '${output}/kotlin-compiler-clean.jar'
|
||||||
|
-outjars '${output}/kotlin-compiler.jar'
|
||||||
|
|
||||||
|
-libraryjars '${rtjar}'
|
||||||
|
|
||||||
|
-target 1.6
|
||||||
|
-dontoptimize
|
||||||
|
-dontobfuscate
|
||||||
|
|
||||||
|
# Keep application classes, along with their 'main' methods.
|
||||||
|
-keepclasseswithmembers public class * {
|
||||||
|
public static void main(java.lang.String[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
# Various dynamically called methods
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
void dispose();
|
||||||
|
** getFileSystem();
|
||||||
|
** isVarArgs();
|
||||||
|
** getApplication();
|
||||||
|
** finalizeReferent();
|
||||||
|
** newBuilder();
|
||||||
|
** startFinalizer(java.lang.Class,java.lang.Object);
|
||||||
|
** executeOnPooledThread(java.lang.Runnable);
|
||||||
|
** getUserData(java.lang.String);
|
||||||
|
int getBooleanAttributes(java.io.File);
|
||||||
|
<init>(kotlinc.internal.com.intellij.lang.ASTNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Keep the special static methods that are required in enumeration classes.
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class * {
|
||||||
|
** toString();
|
||||||
|
** hashCode();
|
||||||
|
** project();
|
||||||
|
|
||||||
|
** TYPE;
|
||||||
|
** ourInstance;
|
||||||
|
}
|
||||||
|
]]></proguard>
|
||||||
|
<delete file="${output}/kotlin-compiler-clean.jar" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="clean">
|
<target name="clean">
|
||||||
|
|||||||
Binary file not shown.
@@ -79,7 +79,7 @@ public class CallableMethod implements Callable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setNeedsReceiver(@Nullable CallableDescriptor receiverClass) {
|
public void setNeedsReceiver(@Nullable CallableDescriptor receiverClass) {
|
||||||
this.receiverFunction = receiverClass;
|
this.receiverFunction = receiverClass.getOriginal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JetType getThisType() {
|
public JetType getThisType() {
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
catch (Throwable error) {
|
catch (Throwable error) {
|
||||||
throw new CompilationException(error.getMessage(), error, selector);
|
String message = error.getMessage();
|
||||||
|
throw new CompilationException(message != null ? message : "null", error, selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,7 +889,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markLineNumber(JetElement statement) {
|
private void markLineNumber(@NotNull JetElement statement) {
|
||||||
final Document document = statement.getContainingFile().getViewProvider().getDocument();
|
final Document document = statement.getContainingFile().getViewProvider().getDocument();
|
||||||
if (document != null) {
|
if (document != null) {
|
||||||
int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset()); // 0-based
|
int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset()); // 0-based
|
||||||
@@ -963,13 +964,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||||
|
VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||||
|
resolvedCall = call.getVariableCall();
|
||||||
|
}
|
||||||
receiver = StackValue.receiver(resolvedCall, receiver, this, null, state);
|
receiver = StackValue.receiver(resolvedCall, receiver, this, null, state);
|
||||||
descriptor = resolvedCall.getResultingDescriptor();
|
descriptor = resolvedCall.getResultingDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof VariableAsFunctionDescriptor) {
|
//if (descriptor instanceof VariableAsFunctionDescriptor) {
|
||||||
descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
|
// descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
|
||||||
}
|
//}
|
||||||
|
|
||||||
final IntrinsicMethod intrinsic = state.getInjector().getIntrinsics().getIntrinsic(descriptor);
|
final IntrinsicMethod intrinsic = state.getInjector().getIntrinsics().getIntrinsic(descriptor);
|
||||||
if (intrinsic != null) {
|
if (intrinsic != null) {
|
||||||
@@ -1254,14 +1259,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else if (funDescriptor instanceof FunctionDescriptor) {
|
else if (funDescriptor instanceof FunctionDescriptor) {
|
||||||
final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
|
final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
|
||||||
return invokeFunction(expression, fd, receiver);
|
if(resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||||
|
VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||||
|
ResolvedCallWithTrace<FunctionDescriptor> functionCall = call.getFunctionCall();
|
||||||
|
return invokeFunction(expression, functionCall.getResultingDescriptor(), receiver, functionCall);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return invokeFunction(expression, fd, receiver, resolvedCall);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor);
|
throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackValue invokeFunction(JetCallExpression expression, DeclarationDescriptor fd, StackValue receiver) {
|
private StackValue invokeFunction(JetCallExpression expression,
|
||||||
|
DeclarationDescriptor fd,
|
||||||
|
StackValue receiver,
|
||||||
|
ResolvedCall<? extends CallableDescriptor> resolvedCall) {
|
||||||
boolean superCall = false;
|
boolean superCall = false;
|
||||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||||
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||||
@@ -1294,8 +1309,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType);
|
return returnValueAsStackValue((FunctionDescriptor) fd, callReturnType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
|
||||||
assert resolvedCall != null;
|
|
||||||
receiver = StackValue.receiver(resolvedCall, receiver, this, null, state);
|
receiver = StackValue.receiver(resolvedCall, receiver, this, null, state);
|
||||||
|
|
||||||
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||||
@@ -1323,11 +1336,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
if (fd instanceof VariableAsFunctionDescriptor) {
|
//if (fd instanceof VariableAsFunctionDescriptor) {
|
||||||
assert !superCall;
|
// assert !superCall;
|
||||||
callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
|
// callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
|
||||||
}
|
//}
|
||||||
else if (fd instanceof ExpressionAsFunctionDescriptor || (fd instanceof SimpleFunctionDescriptor && fd.getContainingDeclaration() instanceof FunctionDescriptor)) {
|
if (fd instanceof ExpressionAsFunctionDescriptor || (fd instanceof SimpleFunctionDescriptor && fd.getContainingDeclaration() instanceof FunctionDescriptor)) {
|
||||||
SimpleFunctionDescriptor invoke = CodegenUtil.createInvoke((FunctionDescriptor) fd);
|
SimpleFunctionDescriptor invoke = CodegenUtil.createInvoke((FunctionDescriptor) fd);
|
||||||
callableMethod = ClosureCodegen.asCallableMethod(invoke);
|
callableMethod = ClosureCodegen.asCallableMethod(invoke);
|
||||||
}
|
}
|
||||||
@@ -1350,6 +1363,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
||||||
assert resolvedCall != null;
|
assert resolvedCall != null;
|
||||||
|
|
||||||
|
if(resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||||
|
resolvedCall = ((VariableAsFunctionResolvedCall)resolvedCall).getFunctionCall();
|
||||||
|
}
|
||||||
|
|
||||||
if(!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
|
if(!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
|
||||||
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod, state);
|
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod, state);
|
||||||
receiver.put(receiver.type, v);
|
receiver.put(receiver.type, v);
|
||||||
@@ -1396,7 +1413,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
else if(descriptor instanceof ExpressionReceiver) {
|
else if(descriptor instanceof ExpressionReceiver) {
|
||||||
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
|
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
|
||||||
JetExpression expr = expressionReceiver.getExpression();
|
JetExpression expr = expressionReceiver.getExpression();
|
||||||
Type exprType = expressionType(expr);
|
Type exprType = asmType(expressionReceiver.getType());
|
||||||
gen(expr, exprType);
|
gen(expr, exprType);
|
||||||
if(type != null)
|
if(type != null)
|
||||||
StackValue.onStack(exprType).put(type, v);
|
StackValue.onStack(exprType).put(type, v);
|
||||||
@@ -1529,15 +1546,55 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
Type type = asmType(outType);
|
Type type = asmType(outType);
|
||||||
assert type.getSort() == Type.ARRAY;
|
assert type.getSort() == Type.ARRAY;
|
||||||
Type elementType = correctElementType(type);
|
Type elementType = correctElementType(type);
|
||||||
int size = valueArgument.getArguments().size();
|
List<ValueArgument> arguments = valueArgument.getArguments();
|
||||||
|
int size = arguments.size();
|
||||||
|
|
||||||
v.iconst(valueArgument.getArguments().size());
|
boolean hasSpread = false;
|
||||||
v.newarray(elementType);
|
|
||||||
for(int i = 0; i != size; ++i) {
|
for(int i = 0; i != size; ++i) {
|
||||||
v.dup();
|
if(arguments.get(i).getSpreadElement() != null) {
|
||||||
v.iconst(i);
|
hasSpread = true;
|
||||||
gen(valueArgument.getArguments().get(i).getArgumentExpression(), elementType);
|
break;
|
||||||
StackValue.arrayElement(elementType, false).store(v);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasSpread) {
|
||||||
|
if(size == 1) {
|
||||||
|
gen(arguments.get(0).getArgumentExpression(), type);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String owner = "jet/runtime/Intrinsics$SpreadBuilder";
|
||||||
|
v.anew(Type.getObjectType(owner));
|
||||||
|
v.dup();
|
||||||
|
v.invokespecial(owner, "<init>", "()V");
|
||||||
|
for(int i = 0; i != size; ++i) {
|
||||||
|
v.dup();
|
||||||
|
ValueArgument argument = arguments.get(i);
|
||||||
|
if(argument.getSpreadElement() != null) {
|
||||||
|
gen(argument.getArgumentExpression(),JetTypeMapper.TYPE_OBJECT);
|
||||||
|
v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gen(argument.getArgumentExpression(), elementType);
|
||||||
|
v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z");
|
||||||
|
v.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.dup();
|
||||||
|
v.invokevirtual(owner, "size", "()I");
|
||||||
|
v.newarray(elementType);
|
||||||
|
v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
|
||||||
|
v.checkcast(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.iconst(arguments.size());
|
||||||
|
v.newarray(elementType);
|
||||||
|
for(int i = 0; i != size; ++i) {
|
||||||
|
v.dup();
|
||||||
|
v.iconst(i);
|
||||||
|
gen(arguments.get(i).getArgumentExpression(), elementType);
|
||||||
|
StackValue.arrayElement(elementType, false).store(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class FunctionCodegen {
|
|||||||
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
|
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
|
||||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
||||||
av.writeName(parameterDescriptor.getName());
|
av.writeName(parameterDescriptor.getName());
|
||||||
av.writeHasDefaultValue(parameterDescriptor.hasDefaultValue());
|
av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue());
|
||||||
av.writeNullable(parameterDescriptor.getType().isNullable());
|
av.writeNullable(parameterDescriptor.getType().isNullable());
|
||||||
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
|
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
|
||||||
av.writeType(jvmSignature.getKotlinParameterTypes().get(i + start).getKotlinSignature());
|
av.writeType(jvmSignature.getKotlinParameterTypes().get(i + start).getKotlinSignature());
|
||||||
@@ -312,7 +312,7 @@ public class FunctionCodegen {
|
|||||||
boolean needed = false;
|
boolean needed = false;
|
||||||
if(functionDescriptor != null) {
|
if(functionDescriptor != null) {
|
||||||
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
|
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
|
||||||
if(parameterDescriptor.hasDefaultValue()) {
|
if(parameterDescriptor.declaresDefaultValue()) {
|
||||||
needed = true;
|
needed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -398,7 +398,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
Type t = argumentTypes[extra + index];
|
Type t = argumentTypes[extra + index];
|
||||||
Label endArg = null;
|
Label endArg = null;
|
||||||
if (parameterDescriptor.hasDefaultValue()) {
|
if (parameterDescriptor.declaresDefaultValue()) {
|
||||||
iv.load(maskIndex, Type.INT_TYPE);
|
iv.load(maskIndex, Type.INT_TYPE);
|
||||||
iv.iconst(1 << index);
|
iv.iconst(1 << index);
|
||||||
iv.and(Type.INT_TYPE);
|
iv.and(Type.INT_TYPE);
|
||||||
@@ -418,7 +418,7 @@ public class FunctionCodegen {
|
|||||||
iv.load(var, t);
|
iv.load(var, t);
|
||||||
var += t.getSize();
|
var += t.getSize();
|
||||||
|
|
||||||
if (parameterDescriptor.hasDefaultValue()) {
|
if (parameterDescriptor.declaresDefaultValue()) {
|
||||||
iv.mark(endArg);
|
iv.mark(endArg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,22 +446,22 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean differentMethods(Method method, Method overriden) {
|
private static boolean differentMethods(Method method, Method overridden) {
|
||||||
if(!method.getReturnType().equals(overriden.getReturnType()))
|
if(!method.getReturnType().equals(overridden.getReturnType()))
|
||||||
return true;
|
return true;
|
||||||
Type[] methodArgumentTypes = method.getArgumentTypes();
|
Type[] methodArgumentTypes = method.getArgumentTypes();
|
||||||
Type[] overridenArgumentTypes = overriden.getArgumentTypes();
|
Type[] overriddenArgumentTypes = overridden.getArgumentTypes();
|
||||||
if(methodArgumentTypes.length != overridenArgumentTypes.length)
|
if(methodArgumentTypes.length != overriddenArgumentTypes.length)
|
||||||
return true;
|
return true;
|
||||||
for(int i = 0; i != methodArgumentTypes.length; ++i)
|
for(int i = 0; i != methodArgumentTypes.length; ++i)
|
||||||
if(!methodArgumentTypes[i].equals(overridenArgumentTypes[i]))
|
if(!methodArgumentTypes[i].equals(overriddenArgumentTypes[i]))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkOverride(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
|
private static void checkOverride(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
|
||||||
Method method = state.getInjector().getJetTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor).getAsmMethod();
|
Method method = state.getInjector().getJetTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor).getAsmMethod();
|
||||||
Method overriden = state.getInjector().getJetTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod();
|
Method overridden = state.getInjector().getJetTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod();
|
||||||
|
|
||||||
if(overriddenFunction.getModality() == Modality.ABSTRACT) {
|
if(overriddenFunction.getModality() == Modality.ABSTRACT) {
|
||||||
Set<? extends FunctionDescriptor> overriddenFunctions = overriddenFunction.getOverriddenDescriptors();
|
Set<? extends FunctionDescriptor> overriddenFunctions = overriddenFunction.getOverriddenDescriptors();
|
||||||
@@ -470,17 +470,17 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(differentMethods(method, overriden)) {
|
if(differentMethods(method, overridden)) {
|
||||||
int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO.
|
int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO.
|
||||||
|
|
||||||
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
|
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null);
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||||
StubCodegen.generateStubCode(mv);
|
StubCodegen.generateStubCode(mv);
|
||||||
}
|
}
|
||||||
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
Type[] argTypes = overriden.getArgumentTypes();
|
Type[] argTypes = overridden.getArgumentTypes();
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
@@ -495,11 +495,11 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
iv.invokevirtual(state.getInjector().getJetTypeMapper().mapType(((ClassDescriptor) owner.getContextDescriptor()).getDefaultType(), MapTypeMode.VALUE).getInternalName(), jvmSignature.getName(), jvmSignature.getDescriptor());
|
iv.invokevirtual(state.getInjector().getJetTypeMapper().mapType(((ClassDescriptor) owner.getContextDescriptor()).getDefaultType(), MapTypeMode.VALUE).getInternalName(), jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||||
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
|
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overridden.getReturnType()))
|
||||||
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
||||||
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
|
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
|
||||||
iv.aconst(null);
|
iv.aconst(null);
|
||||||
iv.areturn(overriden.getReturnType());
|
iv.areturn(overridden.getReturnType());
|
||||||
endVisit(mv, "bridge method", BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
endVisit(mv, "bridge method", BindingContextUtils.callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
|
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
|
||||||
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
|
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
|
||||||
jetValueParameterAnnotation.writeName(valueParameter.getName());
|
jetValueParameterAnnotation.writeName(valueParameter.getName());
|
||||||
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.hasDefaultValue());
|
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
|
||||||
jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i));
|
jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i));
|
||||||
jetValueParameterAnnotation.visitEnd();
|
jetValueParameterAnnotation.visitEnd();
|
||||||
++i;
|
++i;
|
||||||
@@ -1024,18 +1024,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<CallableMemberDescriptor> overridenDeclarations = OverridingUtil.getOverridenDeclarations(callableMemberDescriptor);
|
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor);
|
||||||
for (CallableMemberDescriptor overridenDeclaration : overridenDeclarations) {
|
for (CallableMemberDescriptor overriddenDeclaration : overriddenDeclarations) {
|
||||||
if (overridenDeclaration.getModality() != Modality.ABSTRACT) {
|
if (overriddenDeclaration.getModality() != Modality.ABSTRACT) {
|
||||||
if (!CodegenUtil.isInterface(overridenDeclaration.getContainingDeclaration())) {
|
if (!CodegenUtil.isInterface(overriddenDeclaration.getContainingDeclaration())) {
|
||||||
continue root;
|
continue root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CallableMemberDescriptor overridenDeclaration : overridenDeclarations) {
|
for (CallableMemberDescriptor overriddenDeclaration : overriddenDeclarations) {
|
||||||
if (overridenDeclaration.getModality() != Modality.ABSTRACT) {
|
if (overriddenDeclaration.getModality() != Modality.ABSTRACT) {
|
||||||
r.add(Pair.create(callableMemberDescriptor, overridenDeclaration));
|
r.add(Pair.create(callableMemberDescriptor, overriddenDeclaration));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ public class JetTypeMapper {
|
|||||||
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
|
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
|
||||||
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
|
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
|
||||||
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
|
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
|
||||||
|
public static final Type JL_ARRAY_LIST = Type.getObjectType("java/util/ArrayList");
|
||||||
public static final Type JL_STRING_TYPE = Type.getObjectType("java/lang/String");
|
public static final Type JL_STRING_TYPE = Type.getObjectType("java/lang/String");
|
||||||
public static final Type JL_CHAR_SEQUENCE_TYPE = Type.getObjectType("java/lang/CharSequence");
|
public static final Type JL_CHAR_SEQUENCE_TYPE = Type.getObjectType("java/lang/CharSequence");
|
||||||
private static final Type JL_COMPARABLE_TYPE = Type.getObjectType("java/lang/Comparable");
|
private static final Type JL_COMPARABLE_TYPE = Type.getObjectType("java/lang/Comparable");
|
||||||
@@ -941,9 +942,10 @@ public class JetTypeMapper {
|
|||||||
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE));
|
return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType(), MapTypeMode.VALUE));
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof VariableDescriptor) {
|
else if (descriptor instanceof VariableDescriptor) {
|
||||||
Boolean aBoolean = bindingContext.get(BindingContext.MUST_BE_WRAPPED_IN_A_REF, (VariableDescriptor) descriptor);
|
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
|
||||||
if (aBoolean != null && aBoolean) {
|
Boolean aBoolean = bindingContext.get(BindingContext.CAPTURED_IN_CLOSURE, variableDescriptor);
|
||||||
JetType outType = ((VariableDescriptor) descriptor).getType();
|
if (aBoolean != null && aBoolean && variableDescriptor.isVar()) {
|
||||||
|
JetType outType = variableDescriptor.getType();
|
||||||
return StackValue.sharedTypeForType(mapType(outType, MapTypeMode.VALUE));
|
return StackValue.sharedTypeForType(mapType(outType, MapTypeMode.VALUE));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ import java.util.List;
|
|||||||
public class Concat implements IntrinsicMethod {
|
public class Concat implements IntrinsicMethod {
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver, @NotNull GenerationState state) {
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver, @NotNull GenerationState state) {
|
||||||
codegen.generateStringBuilderConstructor();
|
|
||||||
if (receiver == null || receiver == StackValue.none()) { // LHS + RHS
|
if (receiver == null || receiver == StackValue.none()) { // LHS + RHS
|
||||||
|
codegen.generateStringBuilderConstructor();
|
||||||
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
|
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
|
||||||
codegen.invokeAppend(arguments.get(1));
|
codegen.invokeAppend(arguments.get(1));
|
||||||
}
|
}
|
||||||
else { // LHS.plus(RHS)
|
else { // LHS.plus(RHS)
|
||||||
|
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
|
codegen.generateStringBuilderConstructor();
|
||||||
v.swap(); // StringBuilder LHS
|
v.swap(); // StringBuilder LHS
|
||||||
codegen.invokeAppendMethod(expectedType); // StringBuilder(LHS)
|
codegen.invokeAppendMethod(expectedType); // StringBuilder(LHS)
|
||||||
codegen.invokeAppend(arguments.get(0));
|
codegen.invokeAppend(arguments.get(0));
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<orderEntry type="module" module-name="jet.as.java.psi" />
|
<orderEntry type="module" module-name="jet.as.java.psi" />
|
||||||
<orderEntry type="library" name="intellij-core" level="project" />
|
<orderEntry type="library" name="intellij-core" level="project" />
|
||||||
<orderEntry type="library" name="asm" level="project" />
|
<orderEntry type="library" name="asm" level="project" />
|
||||||
|
<orderEntry type="module" module-name="js.translator" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* 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.cli.common;
|
||||||
|
|
||||||
|
import com.sampullara.cli.Args;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.MessageRenderer;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentException;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.cli.common.ExitCode.INTERNAL_ERROR;
|
||||||
|
import static org.jetbrains.jet.cli.common.ExitCode.OK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Pavel Talanov
|
||||||
|
*/
|
||||||
|
public abstract class CLICompiler<A extends CompilerArguments, C extends CompileEnvironmentConfiguration> {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ExitCode exec(@NotNull PrintStream errStream, @NotNull String... args) {
|
||||||
|
A arguments = createArguments();
|
||||||
|
if (!parseArguments(errStream, arguments, args)) {
|
||||||
|
return INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
return exec(errStream, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the arguments can be parsed correctly
|
||||||
|
*/
|
||||||
|
protected boolean parseArguments(@NotNull PrintStream errStream, @NotNull A arguments, @NotNull String[] args) {
|
||||||
|
try {
|
||||||
|
Args.parse(arguments, args);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
usage(errStream);
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
// Always use tags
|
||||||
|
errStream.println(MessageRenderer.TAGS.renderException(t));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow derived classes to add additional command line arguments
|
||||||
|
*/
|
||||||
|
protected void usage(@NotNull PrintStream target) {
|
||||||
|
// We should say something like
|
||||||
|
// Args.usage(target, K2JVMCompilerArguments.class);
|
||||||
|
// but currently cli-parser we are using does not support that
|
||||||
|
// a corresponding patch has been sent to the authors
|
||||||
|
// For now, we are using this:
|
||||||
|
PrintStream oldErr = System.err;
|
||||||
|
System.setErr(target);
|
||||||
|
try {
|
||||||
|
// TODO: use proper argv0
|
||||||
|
Args.usage(createArguments());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
System.setErr(oldErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strategy method to configure the environment, allowing compiler
|
||||||
|
* based tools to customise their own plugins
|
||||||
|
*/
|
||||||
|
//TODO: add parameter annotations when KT-1863 is resolved
|
||||||
|
protected void configureEnvironment(@NotNull C configuration, @NotNull A arguments) {
|
||||||
|
List<CompilerPlugin> plugins = arguments.getCompilerPlugins();
|
||||||
|
configuration.getCompilerPlugins().addAll(plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected abstract A createArguments();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the compiler on the parsed arguments
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public ExitCode exec(final PrintStream errStream, A arguments) {
|
||||||
|
if (arguments.isHelp()) {
|
||||||
|
usage(errStream);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
System.setProperty("java.awt.headless", "true");
|
||||||
|
final MessageRenderer messageRenderer = getMessageRenderer(arguments);
|
||||||
|
errStream.print(messageRenderer.renderPreamble());
|
||||||
|
printVersionIfNeeded(errStream, arguments, messageRenderer);
|
||||||
|
try {
|
||||||
|
return doExecute(errStream, arguments, messageRenderer);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
errStream.print(messageRenderer.renderConclusion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: can't declare parameters as not null due to KT-1863
|
||||||
|
@NotNull
|
||||||
|
protected abstract ExitCode doExecute(PrintStream stream, A arguments, MessageRenderer renderer);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private MessageRenderer getMessageRenderer(@NotNull A arguments) {
|
||||||
|
return arguments.isTags() ? MessageRenderer.TAGS : MessageRenderer.PLAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void printVersionIfNeeded(@NotNull PrintStream errStream,
|
||||||
|
@NotNull A arguments,
|
||||||
|
@NotNull MessageRenderer messageRenderer) {
|
||||||
|
if (arguments.isVersion()) {
|
||||||
|
String versionMessage = messageRenderer.render(CompilerMessageSeverity.INFO,
|
||||||
|
"Kotlin Compiler version " + CompilerVersion.VERSION,
|
||||||
|
CompilerMessageLocation.NO_LOCATION);
|
||||||
|
errStream.println(versionMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful main for derived command line tools
|
||||||
|
*/
|
||||||
|
public static void doMain(@NotNull CLICompiler compiler, @NotNull String[] args) {
|
||||||
|
try {
|
||||||
|
ExitCode rc = compiler.exec(System.out, args);
|
||||||
|
if (rc != OK) {
|
||||||
|
System.err.println("exec() finished with " + rc + " return code");
|
||||||
|
System.exit(rc.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CompileEnvironmentException e) {
|
||||||
|
System.err.println(e.getMessage());
|
||||||
|
System.exit(INTERNAL_ERROR.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-22
@@ -14,45 +14,32 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.jet.cli.jvm.compiler;
|
package org.jetbrains.jet.cli.common;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.util.Disposer;
|
import com.intellij.openapi.util.Disposer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.cli.common.CompilerPlugin;
|
|
||||||
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
||||||
import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
public class CompileEnvironmentConfiguration {
|
public abstract class CompileEnvironmentConfiguration {
|
||||||
private final JetCoreEnvironment environment;
|
|
||||||
private final CompilerDependencies compilerDependencies;
|
|
||||||
private final MessageCollector messageCollector;
|
|
||||||
|
|
||||||
private List<CompilerPlugin> compilerPlugins = Lists.newArrayList();
|
@NotNull
|
||||||
|
private final MessageCollector messageCollector;
|
||||||
|
@NotNull
|
||||||
|
private final List<CompilerPlugin> compilerPlugins = Lists.newArrayList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: It's very important to call dispose for every object of this class or there will be memory leaks.
|
* NOTE: It's very important to call dispose for every object of this class or there will be memory leaks.
|
||||||
|
*
|
||||||
* @see Disposer
|
* @see Disposer
|
||||||
*/
|
*/
|
||||||
public CompileEnvironmentConfiguration(@NotNull JetCoreEnvironment environment,
|
public CompileEnvironmentConfiguration(@NotNull MessageCollector messageCollector) {
|
||||||
@NotNull CompilerDependencies compilerDependencies, @NotNull MessageCollector messageCollector) {
|
|
||||||
this.messageCollector = messageCollector;
|
this.messageCollector = messageCollector;
|
||||||
this.compilerDependencies = compilerDependencies;
|
|
||||||
this.environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JetCoreEnvironment getEnvironment() {
|
|
||||||
return environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public CompilerDependencies getCompilerDependencies() {
|
|
||||||
return compilerDependencies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -60,6 +47,7 @@ public class CompileEnvironmentConfiguration {
|
|||||||
return messageCollector;
|
return messageCollector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public List<CompilerPlugin> getCompilerPlugins() {
|
public List<CompilerPlugin> getCompilerPlugins() {
|
||||||
return compilerPlugins;
|
return compilerPlugins;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.cli.common;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.sampullara.cli.Argument;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Pavel Talanov
|
||||||
|
*/
|
||||||
|
public abstract class CompilerArguments {
|
||||||
|
@NotNull
|
||||||
|
private List<CompilerPlugin> compilerPlugins = Lists.newArrayList();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<CompilerPlugin> getCompilerPlugins() {
|
||||||
|
return compilerPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the compiler plugins to be used when working with the {@link org.jetbrains.jet.cli.CLICompiler}
|
||||||
|
*/
|
||||||
|
public void setCompilerPlugins(@NotNull List<CompilerPlugin> compilerPlugins) {
|
||||||
|
this.compilerPlugins = compilerPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean isHelp();
|
||||||
|
public abstract boolean isTags();
|
||||||
|
public abstract boolean isVersion();
|
||||||
|
}
|
||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.cli.common;
|
package org.jetbrains.jet.cli.common;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple interface for compiler plugins to run after the compiler has finished such as for things like
|
* A simple interface for compiler plugins to run after the compiler has finished such as for things like
|
||||||
* generating documentation or code generation etc
|
* generating documentation or code generation etc
|
||||||
*/
|
*/
|
||||||
public interface CompilerPlugin {
|
public interface CompilerPlugin {
|
||||||
void processFiles(CompilerPluginContext context);
|
void processFiles(@NotNull CompilerPluginContext context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.cli.common;
|
package org.jetbrains.jet.cli.common;
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
|
||||||
@@ -27,8 +28,12 @@ import java.util.List;
|
|||||||
* the {@link Project}, the {@link BindingContext} and the underlying {@link JetFile} files.
|
* the {@link Project}, the {@link BindingContext} and the underlying {@link JetFile} files.
|
||||||
*/
|
*/
|
||||||
public class CompilerPluginContext {
|
public class CompilerPluginContext {
|
||||||
|
@NotNull
|
||||||
private final Project project;
|
private final Project project;
|
||||||
|
//TODO: should we in fact store AnalyzeExhaust here?
|
||||||
|
@NotNull
|
||||||
private final BindingContext context;
|
private final BindingContext context;
|
||||||
|
@NotNull
|
||||||
private final List<JetFile> files;
|
private final List<JetFile> files;
|
||||||
|
|
||||||
public CompilerPluginContext(Project project, BindingContext context, List<JetFile> files) {
|
public CompilerPluginContext(Project project, BindingContext context, List<JetFile> files) {
|
||||||
@@ -37,14 +42,17 @@ public class CompilerPluginContext {
|
|||||||
this.files = files;
|
this.files = files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public BindingContext getContext() {
|
public BindingContext getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public List<JetFile> getFiles() {
|
public List<JetFile> getFiles() {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public Project getProject() {
|
public Project getProject() {
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -14,12 +14,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.jet.cli.jvm;
|
package org.jetbrains.jet.cli.common;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class K2JVMCompilerVersion {
|
public class CompilerVersion {
|
||||||
// The value of this constant is generated by the build script
|
// The value of this constant is generated by the build script
|
||||||
// DON'T MODIFY IT
|
// DON'T MODIFY IT
|
||||||
public static final String VERSION = "@snapshot@";
|
public static final String VERSION = "@snapshot@";
|
||||||
@@ -42,7 +42,7 @@ public interface MessageRenderer {
|
|||||||
out.append(" line=\"").append(location.getLine()).append("\"");
|
out.append(" line=\"").append(location.getLine()).append("\"");
|
||||||
out.append(" column=\"").append(location.getColumn()).append("\"");
|
out.append(" column=\"").append(location.getColumn()).append("\"");
|
||||||
}
|
}
|
||||||
out.append(">\n");
|
out.append(">");
|
||||||
|
|
||||||
out.append(e(message));
|
out.append(e(message));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.cli.js;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Disposer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.cli.common.CompileEnvironmentConfiguration;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Pavel Talanov
|
||||||
|
*/
|
||||||
|
public class K2JSCompileEnvironmentConfiguration extends CompileEnvironmentConfiguration {
|
||||||
|
/**
|
||||||
|
* NOTE: It's very important to call dispose for every object of this class or there will be memory leaks.
|
||||||
|
*
|
||||||
|
* @see Disposer
|
||||||
|
*/
|
||||||
|
public K2JSCompileEnvironmentConfiguration(@NotNull MessageCollector messageCollector) {
|
||||||
|
super(messageCollector);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,12 +16,83 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.cli.js;
|
package org.jetbrains.jet.cli.js;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.intellij.openapi.Disposable;
|
||||||
|
import com.intellij.psi.PsiFile;
|
||||||
|
import jet.Function0;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||||
|
import org.jetbrains.jet.cli.common.CLICompiler;
|
||||||
|
import org.jetbrains.jet.cli.common.ExitCode;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.MessageRenderer;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.PrintingMessageCollector;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
|
import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS;
|
||||||
|
import org.jetbrains.k2js.config.Config;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
public final class K2JSCompiler {
|
public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompileEnvironmentConfiguration> {
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
//TODO
|
doMain(new K2JSCompiler(), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected K2JSCompilerArguments createArguments() {
|
||||||
|
return new K2JSCompilerArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected ExitCode doExecute(PrintStream stream, K2JSCompilerArguments arguments, MessageRenderer renderer) {
|
||||||
|
PrintingMessageCollector messageCollector = new PrintingMessageCollector(stream, renderer, true);
|
||||||
|
if (arguments.module != null) {
|
||||||
|
stream.print(renderer.render(CompilerMessageSeverity.ERROR, "Module arg is not supported", NO_LOCATION));
|
||||||
|
return ExitCode.INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.srcdir == null) {
|
||||||
|
stream.print(renderer.render(CompilerMessageSeverity.ERROR, "Specify sources location via -srcdir", NO_LOCATION));
|
||||||
|
return ExitCode.INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable();
|
||||||
|
final JetCoreEnvironment environmentForJS = JetCoreEnvironment.getCoreEnvironmentForJS(rootDisposable);
|
||||||
|
environmentForJS.addSources(arguments.srcdir);
|
||||||
|
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(messageCollector);
|
||||||
|
final List<JetFile> sources = environmentForJS.getSourceFiles();
|
||||||
|
analyzerWithCompilerReport.analyzeAndReport(new Function0<AnalyzeExhaust>() {
|
||||||
|
@Override
|
||||||
|
public AnalyzeExhaust invoke() {
|
||||||
|
BindingContext context = AnalyzerFacadeForJS
|
||||||
|
.analyzeFiles(sources, Predicates.<PsiFile>alwaysTrue(), new Config(environmentForJS.getProject()) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
protected List<JetFile> generateLibFiles() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return AnalyzeExhaust.success(context, JetStandardLibrary.getInstance());
|
||||||
|
}
|
||||||
|
}, sources);
|
||||||
|
|
||||||
|
stream.print(renderer.render(CompilerMessageSeverity.ERROR, "Greeting", NO_LOCATION));
|
||||||
|
return ExitCode.OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,46 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.cli.js;
|
package org.jetbrains.jet.cli.js;
|
||||||
|
|
||||||
|
import com.sampullara.cli.Argument;
|
||||||
|
import org.jetbrains.jet.cli.common.CompilerArguments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pavel Talanov
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
//TODO
|
public class K2JSCompilerArguments extends CompilerArguments {
|
||||||
public class K2JSCompilerArguments {
|
@Argument(value = "output", description = "Output directory")
|
||||||
|
public String outputDir;
|
||||||
|
|
||||||
|
@Argument(value = "module", description = "Module to compile")
|
||||||
|
public String module;
|
||||||
|
|
||||||
|
@Argument(value = "srcdir", description = "Sources directory")
|
||||||
|
public String srcdir;
|
||||||
|
|
||||||
|
@Argument(value = "tags", description = "Demarcate each compilation message (error, warning, etc) with an open and close tag")
|
||||||
|
public boolean tags;
|
||||||
|
|
||||||
|
@Argument(value = "verbose", description = "Enable verbose logging output")
|
||||||
|
public boolean verbose;
|
||||||
|
|
||||||
|
@Argument(value = "version", description = "Display compiler version")
|
||||||
|
public boolean version;
|
||||||
|
|
||||||
|
@Argument(value = "help", alias = "h", description = "show help")
|
||||||
|
public boolean help;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isHelp() {
|
||||||
|
return help;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,16 @@ import com.google.common.base.Splitter;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import com.intellij.openapi.util.Disposer;
|
import com.intellij.openapi.util.Disposer;
|
||||||
import com.sampullara.cli.Args;
|
|
||||||
import jet.modules.Module;
|
import jet.modules.Module;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.cli.common.CompilerPlugin;
|
import org.jetbrains.jet.cli.common.CLICompiler;
|
||||||
import org.jetbrains.jet.cli.common.ExitCode;
|
import org.jetbrains.jet.cli.common.ExitCode;
|
||||||
import org.jetbrains.jet.cli.common.messages.PrintingMessageCollector;
|
|
||||||
import org.jetbrains.jet.codegen.CompilationException;
|
|
||||||
import org.jetbrains.jet.cli.jvm.compiler.*;
|
|
||||||
import org.jetbrains.jet.cli.common.messages.*;
|
import org.jetbrains.jet.cli.common.messages.*;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.K2JVMCompileEnvironmentConfiguration;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||||
|
import org.jetbrains.jet.cli.jvm.compiler.KotlinToJVMBytecodeCompiler;
|
||||||
|
import org.jetbrains.jet.codegen.CompilationException;
|
||||||
import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
|
import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
|
||||||
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
|
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
|
||||||
import org.jetbrains.jet.utils.PathUtil;
|
import org.jetbrains.jet.utils.PathUtil;
|
||||||
@@ -44,138 +45,101 @@ import static org.jetbrains.jet.cli.common.ExitCode.*;
|
|||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||||
public class K2JVMCompiler {
|
public class K2JVMCompiler extends CLICompiler<K2JVMCompilerArguments, K2JVMCompileEnvironmentConfiguration> {
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
doMain(new K2JVMCompiler(), args);
|
doMain(new K2JVMCompiler(), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Useful main for derived command line tools
|
@NotNull
|
||||||
*/
|
protected ExitCode doExecute(PrintStream errStream,
|
||||||
public static void doMain(K2JVMCompiler compiler, String[] args) {
|
K2JVMCompilerArguments arguments,
|
||||||
try {
|
MessageRenderer messageRenderer) {
|
||||||
ExitCode rc = compiler.exec(System.out, args);
|
|
||||||
if (rc != OK) {
|
CompilerSpecialMode mode = parseCompilerSpecialMode(arguments);
|
||||||
System.err.println("exec() finished with " + rc + " return code");
|
File jdkHeadersJar;
|
||||||
System.exit(rc.getCode());
|
if (mode.includeJdkHeaders()) {
|
||||||
|
if (arguments.jdkHeaders != null) {
|
||||||
|
jdkHeadersJar = new File(arguments.jdkHeaders);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jdkHeadersJar = PathUtil.getAltHeadersPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (CompileEnvironmentException e) {
|
else {
|
||||||
System.err.println(e.getMessage());
|
jdkHeadersJar = null;
|
||||||
System.exit(INTERNAL_ERROR.getCode());
|
|
||||||
}
|
}
|
||||||
}
|
File runtimeJar;
|
||||||
|
|
||||||
public ExitCode exec(PrintStream errStream, String... args) {
|
if (mode.includeKotlinRuntime()) {
|
||||||
K2JVMCompilerArguments arguments = createArguments();
|
if (arguments.stdlib != null) {
|
||||||
if (!parseArguments(errStream, arguments, args)) {
|
runtimeJar = new File(arguments.stdlib);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
runtimeJar = PathUtil.getDefaultRuntimePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
runtimeJar = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilerDependencies dependencies = new CompilerDependencies(mode, CompilerDependencies.findRtJar(), jdkHeadersJar, runtimeJar);
|
||||||
|
PrintingMessageCollector messageCollector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose);
|
||||||
|
Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable();
|
||||||
|
|
||||||
|
JetCoreEnvironment environment = JetCoreEnvironment.getCoreEnvironmentForJVM(rootDisposable, dependencies);
|
||||||
|
K2JVMCompileEnvironmentConfiguration configuration =
|
||||||
|
new K2JVMCompileEnvironmentConfiguration(environment, messageCollector);
|
||||||
|
|
||||||
|
messageCollector.report(CompilerMessageSeverity.LOGGING, "Configuring the compilation environment",
|
||||||
|
CompilerMessageLocation.NO_LOCATION);
|
||||||
|
try {
|
||||||
|
configureEnvironment(configuration, arguments);
|
||||||
|
|
||||||
|
boolean noErrors;
|
||||||
|
if (arguments.module != null) {
|
||||||
|
List<Module> modules = CompileEnvironmentUtil
|
||||||
|
.loadModuleScript(arguments.module, new PrintingMessageCollector(errStream, messageRenderer, false));
|
||||||
|
File directory = new File(arguments.module).getParentFile();
|
||||||
|
noErrors = KotlinToJVMBytecodeCompiler.compileModules(configuration, modules,
|
||||||
|
directory, 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 = KotlinToJVMBytecodeCompiler.compileBunchOfSourceDirectories(configuration,
|
||||||
|
arguments.getSourceDirs(), arguments.jar,
|
||||||
|
arguments.outputDir,
|
||||||
|
arguments.includeRuntime);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
noErrors = KotlinToJVMBytecodeCompiler.compileBunchOfSources(configuration,
|
||||||
|
arguments.src, arguments.jar, arguments.outputDir,
|
||||||
|
arguments.includeRuntime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return noErrors ? OK : COMPILATION_ERROR;
|
||||||
|
}
|
||||||
|
catch (CompilationException e) {
|
||||||
|
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e),
|
||||||
|
MessageUtil.psiElementToMessageLocation(e.getElement()));
|
||||||
return INTERNAL_ERROR;
|
return INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
return exec(errStream, arguments);
|
catch (Throwable t) {
|
||||||
}
|
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(t),
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the compiler on the parsed arguments
|
|
||||||
*/
|
|
||||||
public ExitCode exec(final PrintStream errStream, K2JVMCompilerArguments arguments) {
|
|
||||||
if (arguments.help) {
|
|
||||||
usage(errStream);
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
System.setProperty("java.awt.headless", "true");
|
|
||||||
|
|
||||||
final MessageRenderer messageRenderer = arguments.tags ? MessageRenderer.TAGS : MessageRenderer.PLAIN;
|
|
||||||
|
|
||||||
errStream.print(messageRenderer.renderPreamble());
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (arguments.version) {
|
|
||||||
errStream.println(messageRenderer.render(CompilerMessageSeverity.INFO, "Kotlin Compiler version " + K2JVMCompilerVersion.VERSION, CompilerMessageLocation.NO_LOCATION));
|
|
||||||
}
|
|
||||||
|
|
||||||
CompilerSpecialMode mode = parseCompilerSpecialMode(arguments);
|
|
||||||
|
|
||||||
File jdkHeadersJar;
|
|
||||||
if (mode.includeJdkHeaders()) {
|
|
||||||
if (arguments.jdkHeaders != null) {
|
|
||||||
jdkHeadersJar = new File(arguments.jdkHeaders);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jdkHeadersJar = PathUtil.getAltHeadersPath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jdkHeadersJar = null;
|
|
||||||
}
|
|
||||||
File runtimeJar;
|
|
||||||
|
|
||||||
if (mode.includeKotlinRuntime()) {
|
|
||||||
if (arguments.stdlib != null) {
|
|
||||||
runtimeJar = new File(arguments.stdlib);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
runtimeJar = PathUtil.getDefaultRuntimePath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
runtimeJar = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompilerDependencies dependencies = new CompilerDependencies(mode, CompilerDependencies.findRtJar(), jdkHeadersJar, runtimeJar);
|
|
||||||
PrintingMessageCollector messageCollector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose);
|
|
||||||
Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable();
|
|
||||||
|
|
||||||
JetCoreEnvironment environment = new JetCoreEnvironment(rootDisposable, dependencies);
|
|
||||||
CompileEnvironmentConfiguration configuration = new CompileEnvironmentConfiguration(environment, dependencies, messageCollector);
|
|
||||||
|
|
||||||
messageCollector.report(CompilerMessageSeverity.LOGGING, "Configuring the compilation environment",
|
|
||||||
CompilerMessageLocation.NO_LOCATION);
|
CompilerMessageLocation.NO_LOCATION);
|
||||||
try {
|
return INTERNAL_ERROR;
|
||||||
configureEnvironment(configuration, arguments);
|
|
||||||
|
|
||||||
boolean noErrors;
|
|
||||||
if (arguments.module != null) {
|
|
||||||
List<Module> modules = CompileEnvironmentUtil.loadModuleScript(arguments.module, new PrintingMessageCollector(errStream, messageRenderer, false));
|
|
||||||
File directory = new File(arguments.module).getParentFile();
|
|
||||||
noErrors = KotlinToJVMBytecodeCompiler.compileModules(configuration, modules,
|
|
||||||
directory, 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 = KotlinToJVMBytecodeCompiler.compileBunchOfSourceDirectories(configuration,
|
|
||||||
arguments.getSourceDirs(), arguments.jar, arguments.outputDir, arguments.includeRuntime);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
noErrors = KotlinToJVMBytecodeCompiler.compileBunchOfSources(configuration,
|
|
||||||
arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return noErrors ? OK : COMPILATION_ERROR;
|
|
||||||
}
|
|
||||||
catch (CompilationException e) {
|
|
||||||
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e),
|
|
||||||
MessageUtil.psiElementToMessageLocation(e.getElement()));
|
|
||||||
return INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
catch (Throwable t) {
|
|
||||||
messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(t), CompilerMessageLocation.NO_LOCATION);
|
|
||||||
return INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
Disposer.dispose(rootDisposable);
|
|
||||||
messageCollector.printToErrStream();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
errStream.print(messageRenderer.renderConclusion());
|
Disposer.dispose(rootDisposable);
|
||||||
|
messageCollector.printToErrStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private CompilerSpecialMode parseCompilerSpecialMode(@NotNull K2JVMCompilerArguments arguments) {
|
private static CompilerSpecialMode parseCompilerSpecialMode(@NotNull K2JVMCompilerArguments arguments) {
|
||||||
if (arguments.mode == null) {
|
if (arguments.mode == null) {
|
||||||
return CompilerSpecialMode.REGULAR;
|
return CompilerSpecialMode.REGULAR;
|
||||||
}
|
}
|
||||||
@@ -190,65 +154,37 @@ public class K2JVMCompiler {
|
|||||||
throw new IllegalArgumentException("unknown compiler mode: " + arguments.mode);
|
throw new IllegalArgumentException("unknown compiler mode: " + arguments.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the arguments can be parsed correctly
|
|
||||||
*/
|
|
||||||
protected boolean parseArguments(PrintStream errStream, K2JVMCompilerArguments arguments, String[] args) {
|
|
||||||
try {
|
|
||||||
Args.parse(arguments, args);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException e) {
|
|
||||||
usage(errStream);
|
|
||||||
}
|
|
||||||
catch (Throwable t) {
|
|
||||||
// Always use tags
|
|
||||||
errStream.println(MessageRenderer.TAGS.renderException(t));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void usage(PrintStream target) {
|
|
||||||
// We should say something like
|
|
||||||
// Args.usage(target, K2JVMCompilerArguments.class);
|
|
||||||
// but currently cli-parser we are using does not support that
|
|
||||||
// a corresponding patch has been sent to the authors
|
|
||||||
// For now, we are using this:
|
|
||||||
|
|
||||||
PrintStream oldErr = System.err;
|
|
||||||
System.setErr(target);
|
|
||||||
try {
|
|
||||||
// TODO: use proper argv0
|
|
||||||
Args.usage(new K2JVMCompilerArguments());
|
|
||||||
} finally {
|
|
||||||
System.setErr(oldErr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow derived classes to add additional command line arguments
|
* Allow derived classes to add additional command line arguments
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
protected K2JVMCompilerArguments createArguments() {
|
protected K2JVMCompilerArguments createArguments() {
|
||||||
return new K2JVMCompilerArguments();
|
return new K2JVMCompilerArguments();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//TODO: Hacked! Be sure that our kotlin stuff builds correctly before you remove.
|
||||||
* Strategy method to configure the environment, allowing compiler
|
// our compiler throws method not found error
|
||||||
* based tools to customise their own plugins
|
// probably relates to KT-1863... well, may be not
|
||||||
*/
|
@NotNull
|
||||||
protected void configureEnvironment(CompileEnvironmentConfiguration configuration, K2JVMCompilerArguments arguments) {
|
@Override
|
||||||
// install any compiler plugins
|
public ExitCode exec(PrintStream errStream, K2JVMCompilerArguments arguments) {
|
||||||
List<CompilerPlugin> plugins = arguments.getCompilerPlugins();
|
return super.exec(errStream, arguments);
|
||||||
if (plugins != null) {
|
}
|
||||||
configuration.getCompilerPlugins().addAll(plugins);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configuration.getCompilerDependencies().getRuntimeJar() != null) {
|
|
||||||
CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), configuration.getCompilerDependencies().getRuntimeJar());
|
@Override
|
||||||
|
protected void configureEnvironment(@NotNull K2JVMCompileEnvironmentConfiguration configuration, @NotNull K2JVMCompilerArguments arguments) {
|
||||||
|
super.configureEnvironment(configuration, arguments);
|
||||||
|
|
||||||
|
if (configuration.getEnvironment().getCompilerDependencies().getRuntimeJar() != null) {
|
||||||
|
CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(),
|
||||||
|
configuration.getEnvironment().getCompilerDependencies().getRuntimeJar());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.classpath != null) {
|
if (arguments.classpath != null) {
|
||||||
final Iterable<String> classpath = Splitter.on(File.pathSeparatorChar).split(arguments.classpath);
|
Iterable<String> classpath = Splitter.on(File.pathSeparatorChar).split(arguments.classpath);
|
||||||
CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), Iterables.toArray(classpath, String.class));
|
CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), Iterables.toArray(classpath, String.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,15 @@
|
|||||||
package org.jetbrains.jet.cli.jvm;
|
package org.jetbrains.jet.cli.jvm;
|
||||||
|
|
||||||
import com.sampullara.cli.Argument;
|
import com.sampullara.cli.Argument;
|
||||||
import org.jetbrains.jet.cli.common.CompilerPlugin;
|
import org.jetbrains.jet.cli.common.CompilerArguments;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command line arguments for the {@link K2JVMCompiler}
|
* Command line arguments for the {@link K2JVMCompiler}
|
||||||
*/
|
*/
|
||||||
public class K2JVMCompilerArguments {
|
public class K2JVMCompilerArguments extends CompilerArguments {
|
||||||
private List<CompilerPlugin> compilerPlugins = new ArrayList<CompilerPlugin>();
|
|
||||||
|
|
||||||
// TODO ideally we'd unify this with 'src' to just having a single field that supports multiple files/dirs
|
// TODO ideally we'd unify this with 'src' to just having a single field that supports multiple files/dirs
|
||||||
private List<String> sourceDirs;
|
private List<String> sourceDirs;
|
||||||
@@ -40,18 +39,12 @@ public class K2JVMCompilerArguments {
|
|||||||
this.sourceDirs = sourceDirs;
|
this.sourceDirs = sourceDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Argument(value = "output", description = "output directory")
|
|
||||||
public String outputDir;
|
|
||||||
|
|
||||||
@Argument(value = "jar", description = "jar file name")
|
@Argument(value = "jar", description = "jar file name")
|
||||||
public String jar;
|
public String jar;
|
||||||
|
|
||||||
@Argument(value = "src", description = "source file or directory")
|
@Argument(value = "src", description = "source file or directory")
|
||||||
public String src;
|
public String src;
|
||||||
|
|
||||||
@Argument(value = "module", description = "module to compile")
|
|
||||||
public String module;
|
|
||||||
|
|
||||||
@Argument(value = "classpath", description = "classpath to use when compiling")
|
@Argument(value = "classpath", description = "classpath to use when compiling")
|
||||||
public String classpath;
|
public String classpath;
|
||||||
|
|
||||||
@@ -64,12 +57,15 @@ public class K2JVMCompilerArguments {
|
|||||||
@Argument(value = "jdkHeaders", description = "Path to the kotlin-jdk-headers.jar")
|
@Argument(value = "jdkHeaders", description = "Path to the kotlin-jdk-headers.jar")
|
||||||
public String jdkHeaders;
|
public String jdkHeaders;
|
||||||
|
|
||||||
@Argument(value = "help", alias = "h", description = "show help")
|
|
||||||
public boolean help;
|
|
||||||
|
|
||||||
@Argument(value = "mode", description = "Special compiler modes: stubs or jdkHeaders")
|
@Argument(value = "mode", description = "Special compiler modes: stubs or jdkHeaders")
|
||||||
public String mode;
|
public String mode;
|
||||||
|
|
||||||
|
@Argument(value = "output", description = "output directory")
|
||||||
|
public String outputDir;
|
||||||
|
|
||||||
|
@Argument(value = "module", description = "module to compile")
|
||||||
|
public String module;
|
||||||
|
|
||||||
@Argument(value = "tags", description = "Demarcate each compilation message (error, warning, etc) with an open and close tag")
|
@Argument(value = "tags", description = "Demarcate each compilation message (error, warning, etc) with an open and close tag")
|
||||||
public boolean tags;
|
public boolean tags;
|
||||||
|
|
||||||
@@ -79,6 +75,8 @@ public class K2JVMCompilerArguments {
|
|||||||
@Argument(value = "version", description = "Display compiler version")
|
@Argument(value = "version", description = "Display compiler version")
|
||||||
public boolean version;
|
public boolean version;
|
||||||
|
|
||||||
|
@Argument(value = "help", alias = "h", description = "show help")
|
||||||
|
public boolean help;
|
||||||
|
|
||||||
public String getClasspath() {
|
public String getClasspath() {
|
||||||
return classpath;
|
return classpath;
|
||||||
@@ -88,6 +86,7 @@ public class K2JVMCompilerArguments {
|
|||||||
this.classpath = classpath;
|
this.classpath = classpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isHelp() {
|
public boolean isHelp() {
|
||||||
return help;
|
return help;
|
||||||
}
|
}
|
||||||
@@ -144,22 +143,17 @@ public class K2JVMCompilerArguments {
|
|||||||
this.stdlib = stdlib;
|
this.stdlib = stdlib;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isTags() {
|
public boolean isTags() {
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTags(boolean tags) {
|
public void setTags(boolean tags) {
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CompilerPlugin> getCompilerPlugins() {
|
|
||||||
return compilerPlugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the compiler plugins to be used when working with the {@link K2JVMCompiler}
|
|
||||||
*/
|
|
||||||
public void setCompilerPlugins(List<CompilerPlugin> compilerPlugins) {
|
|
||||||
this.compilerPlugins = compilerPlugins;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.intellij.psi.search.GlobalSearchScope;
|
|||||||
import com.intellij.util.Processor;
|
import com.intellij.util.Processor;
|
||||||
import jet.modules.AllModules;
|
import jet.modules.AllModules;
|
||||||
import jet.modules.Module;
|
import jet.modules.Module;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
||||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||||
@@ -61,7 +62,7 @@ public class CompileEnvironmentUtil {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static File getUnpackedRuntimePath() {
|
public static File getUnpackedRuntimePath() {
|
||||||
URL url = CompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class");
|
URL url = K2JVMCompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class");
|
||||||
if (url != null && url.getProtocol().equals("file")) {
|
if (url != null && url.getProtocol().equals("file")) {
|
||||||
return new File(url.getPath()).getParentFile().getParentFile();
|
return new File(url.getPath()).getParentFile().getParentFile();
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ public class CompileEnvironmentUtil {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static File getRuntimeJarPath() {
|
public static File getRuntimeJarPath() {
|
||||||
URL url = CompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class");
|
URL url = K2JVMCompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class");
|
||||||
if (url != null && url.getProtocol().equals("jar")) {
|
if (url != null && url.getProtocol().equals("jar")) {
|
||||||
String path = url.getPath();
|
String path = url.getPath();
|
||||||
return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/")));
|
return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/")));
|
||||||
@@ -157,12 +158,12 @@ public class CompileEnvironmentUtil {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
CompilerDependencies dependencies = CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR);
|
CompilerDependencies dependencies = CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR);
|
||||||
JetCoreEnvironment scriptEnvironment = new JetCoreEnvironment(disposable, dependencies);
|
JetCoreEnvironment scriptEnvironment = JetCoreEnvironment.getCoreEnvironmentForJVM(disposable, dependencies);
|
||||||
ensureRuntime(scriptEnvironment, dependencies);
|
ensureRuntime(scriptEnvironment, dependencies);
|
||||||
scriptEnvironment.addSources(moduleScriptFile);
|
scriptEnvironment.addSources(moduleScriptFile);
|
||||||
|
|
||||||
GenerationState generationState = KotlinToJVMBytecodeCompiler
|
GenerationState generationState = KotlinToJVMBytecodeCompiler
|
||||||
.analyzeAndGenerate(new CompileEnvironmentConfiguration(scriptEnvironment, dependencies, messageCollector), false);
|
.analyzeAndGenerate(new K2JVMCompileEnvironmentConfiguration(scriptEnvironment, messageCollector), false);
|
||||||
if (generationState == null) {
|
if (generationState == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -194,7 +195,7 @@ public class CompileEnvironmentUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
loader = new GeneratedClassLoader(factory, CompileEnvironmentConfiguration.class.getClassLoader());
|
loader = new GeneratedClassLoader(factory, K2JVMCompileEnvironmentConfiguration.class.getClassLoader());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS);
|
Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS);
|
||||||
@@ -337,4 +338,21 @@ public class CompileEnvironmentUtil {
|
|||||||
addToClasspath(environment, new File(path));
|
addToClasspath(environment, new File(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addSourcesFromModuleToEnvironment(@NotNull JetCoreEnvironment environment,
|
||||||
|
@NotNull Module module,
|
||||||
|
@NotNull File moduleDirectory) {
|
||||||
|
for (String sourceFile : module.getSourceFiles()) {
|
||||||
|
File source = new File(sourceFile);
|
||||||
|
if (!source.isAbsolute()) {
|
||||||
|
source = new File(moduleDirectory, sourceFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!source.exists()) {
|
||||||
|
throw new CompileEnvironmentException("'" + source + "' does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
environment.addSources(source.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,24 @@ import java.util.List;
|
|||||||
public class JetCoreEnvironment extends JavaCoreEnvironment {
|
public class JetCoreEnvironment extends JavaCoreEnvironment {
|
||||||
private final List<JetFile> sourceFiles = new ArrayList<JetFile>();
|
private final List<JetFile> sourceFiles = new ArrayList<JetFile>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JetCoreEnvironment getCoreEnvironmentForJS(Disposable disposable) {
|
||||||
|
return new JetCoreEnvironment(disposable, CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.JS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JetCoreEnvironment getCoreEnvironmentForJVM(Disposable disposable, @NotNull CompilerDependencies dependencies) {
|
||||||
|
return new JetCoreEnvironment(disposable, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CompilerDependencies compilerDependencies;
|
||||||
|
|
||||||
public JetCoreEnvironment(Disposable parentDisposable, @NotNull CompilerDependencies compilerDependencies) {
|
public JetCoreEnvironment(Disposable parentDisposable, @NotNull CompilerDependencies compilerDependencies) {
|
||||||
super(parentDisposable);
|
super(parentDisposable);
|
||||||
|
|
||||||
|
this.compilerDependencies = compilerDependencies;
|
||||||
|
|
||||||
registerFileType(JetFileType.INSTANCE, "kt");
|
registerFileType(JetFileType.INSTANCE, "kt");
|
||||||
registerFileType(JetFileType.INSTANCE, "kts");
|
registerFileType(JetFileType.INSTANCE, "kts");
|
||||||
registerFileType(JetFileType.INSTANCE, "ktm");
|
registerFileType(JetFileType.INSTANCE, "ktm");
|
||||||
@@ -72,9 +88,7 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compilerSpecialMode.includeKotlinRuntime()) {
|
if (compilerSpecialMode.includeKotlinRuntime()) {
|
||||||
for (VirtualFile root : compilerDependencies.getRuntimeRoots()) {
|
addToClasspath(compilerDependencies.getRuntimeJar());
|
||||||
addLibraryRoot(root);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JetStandardLibrary.initialize(getProject());
|
JetStandardLibrary.initialize(getProject());
|
||||||
@@ -85,7 +99,7 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addSources(File file) {
|
private void addSources(File file) {
|
||||||
if(file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
File[] files = file.listFiles();
|
File[] files = file.listFiles();
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
for (File child : files) {
|
for (File child : files) {
|
||||||
@@ -97,15 +111,15 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
|
|||||||
VirtualFile fileByPath = getLocalFileSystem().findFileByPath(file.getAbsolutePath());
|
VirtualFile fileByPath = getLocalFileSystem().findFileByPath(file.getAbsolutePath());
|
||||||
if (fileByPath != null) {
|
if (fileByPath != null) {
|
||||||
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(fileByPath);
|
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(fileByPath);
|
||||||
if(psiFile instanceof JetFile) {
|
if (psiFile instanceof JetFile) {
|
||||||
sourceFiles.add((JetFile)psiFile);
|
sourceFiles.add((JetFile) psiFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSources(VirtualFile vFile) {
|
public void addSources(VirtualFile vFile) {
|
||||||
if (vFile.isDirectory()) {
|
if (vFile.isDirectory()) {
|
||||||
for (VirtualFile virtualFile : vFile.getChildren()) {
|
for (VirtualFile virtualFile : vFile.getChildren()) {
|
||||||
addSources(virtualFile);
|
addSources(virtualFile);
|
||||||
}
|
}
|
||||||
@@ -114,15 +128,16 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
|
|||||||
if (vFile.getFileType() == JetFileType.INSTANCE) {
|
if (vFile.getFileType() == JetFileType.INSTANCE) {
|
||||||
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
|
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
|
||||||
if (psiFile instanceof JetFile) {
|
if (psiFile instanceof JetFile) {
|
||||||
sourceFiles.add((JetFile)psiFile);
|
sourceFiles.add((JetFile) psiFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSources(String path) {
|
public void addSources(String path) {
|
||||||
if(path == null)
|
if (path == null) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VirtualFile vFile = getLocalFileSystem().findFileByPath(path);
|
VirtualFile vFile = getLocalFileSystem().findFileByPath(path);
|
||||||
if (vFile == null) {
|
if (vFile == null) {
|
||||||
@@ -141,15 +156,22 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
|
|||||||
|
|
||||||
public void addToClasspathFromClassLoader(ClassLoader loader) {
|
public void addToClasspathFromClassLoader(ClassLoader loader) {
|
||||||
ClassLoader parent = loader.getParent();
|
ClassLoader parent = loader.getParent();
|
||||||
if(parent != null)
|
if (parent != null) {
|
||||||
addToClasspathFromClassLoader(parent);
|
addToClasspathFromClassLoader(parent);
|
||||||
|
}
|
||||||
|
|
||||||
if(loader instanceof URLClassLoader) {
|
if (loader instanceof URLClassLoader) {
|
||||||
for (URL url : ((URLClassLoader) loader).getURLs()) {
|
for (URL url : ((URLClassLoader) loader).getURLs()) {
|
||||||
File file = new File(url.getPath());
|
File file = new File(url.getPath());
|
||||||
if(file.exists() && (!file.isFile() || file.getPath().endsWith(".jar")))
|
if (file.exists() && (!file.isFile() || file.getPath().endsWith(".jar"))) {
|
||||||
addToClasspath(file);
|
addToClasspath(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public CompilerDependencies getCompilerDependencies() {
|
||||||
|
return compilerDependencies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.cli.jvm.compiler;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Disposer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.cli.common.CompileEnvironmentConfiguration;
|
||||||
|
import org.jetbrains.jet.cli.common.messages.MessageCollector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class K2JVMCompileEnvironmentConfiguration extends CompileEnvironmentConfiguration {
|
||||||
|
private final JetCoreEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: It's very important to call dispose for every object of this class or there will be memory leaks.
|
||||||
|
*
|
||||||
|
* @see Disposer
|
||||||
|
*/
|
||||||
|
public K2JVMCompileEnvironmentConfiguration(@NotNull JetCoreEnvironment environment,
|
||||||
|
@NotNull MessageCollector messageCollector) {
|
||||||
|
super(messageCollector);
|
||||||
|
this.environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetCoreEnvironment getEnvironment() {
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-29
@@ -59,7 +59,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static ClassFileFactory compileModule(
|
public static ClassFileFactory compileModule(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
Module moduleBuilder,
|
Module moduleBuilder,
|
||||||
File directory
|
File directory
|
||||||
) {
|
) {
|
||||||
@@ -67,23 +67,12 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
throw new CompileEnvironmentException("No source files where defined");
|
throw new CompileEnvironmentException("No source files where defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String sourceFile : moduleBuilder.getSourceFiles()) {
|
CompileEnvironmentUtil.addSourcesFromModuleToEnvironment(configuration.getEnvironment(), moduleBuilder, directory);
|
||||||
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()) {
|
for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
|
||||||
configuration.getEnvironment().addToClasspath(new File(classpathRoot));
|
configuration.getEnvironment().addToClasspath(new File(classpathRoot));
|
||||||
}
|
}
|
||||||
|
|
||||||
CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getCompilerDependencies());
|
CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getEnvironment().getCompilerDependencies());
|
||||||
|
|
||||||
GenerationState generationState = analyzeAndGenerate(configuration);
|
GenerationState generationState = analyzeAndGenerate(configuration);
|
||||||
if (generationState == null) {
|
if (generationState == null) {
|
||||||
@@ -93,7 +82,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean compileModules(
|
public static boolean compileModules(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
|
|
||||||
@NotNull List<Module> modules,
|
@NotNull List<Module> modules,
|
||||||
|
|
||||||
@@ -104,9 +93,9 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
|
|
||||||
for (Module moduleBuilder : modules) {
|
for (Module moduleBuilder : modules) {
|
||||||
// TODO: this should be done only once for the environment
|
// TODO: this should be done only once for the environment
|
||||||
if (configuration.getCompilerDependencies().getRuntimeJar() != null) {
|
if (configuration.getEnvironment().getCompilerDependencies().getRuntimeJar() != null) {
|
||||||
CompileEnvironmentUtil
|
CompileEnvironmentUtil
|
||||||
.addToClasspath(configuration.getEnvironment(), configuration.getCompilerDependencies().getRuntimeJar());
|
.addToClasspath(configuration.getEnvironment(), configuration.getEnvironment().getCompilerDependencies().getRuntimeJar());
|
||||||
}
|
}
|
||||||
ClassFileFactory moduleFactory = compileModule(configuration, moduleBuilder, directory);
|
ClassFileFactory moduleFactory = compileModule(configuration, moduleBuilder, directory);
|
||||||
if (moduleFactory == null) {
|
if (moduleFactory == null) {
|
||||||
@@ -129,7 +118,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean compileBunchOfSources(
|
private static boolean compileBunchOfSources(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
String jar,
|
String jar,
|
||||||
String outputDir,
|
String outputDir,
|
||||||
boolean includeRuntime
|
boolean includeRuntime
|
||||||
@@ -143,7 +132,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getCompilerDependencies());
|
CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getEnvironment().getCompilerDependencies());
|
||||||
|
|
||||||
GenerationState generationState = analyzeAndGenerate(configuration);
|
GenerationState generationState = analyzeAndGenerate(configuration);
|
||||||
if (generationState == null) {
|
if (generationState == null) {
|
||||||
@@ -174,7 +163,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean compileBunchOfSources(
|
public static boolean compileBunchOfSources(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
|
|
||||||
String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) {
|
String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) {
|
||||||
configuration.getEnvironment().addSources(sourceFileOrDir);
|
configuration.getEnvironment().addSources(sourceFileOrDir);
|
||||||
@@ -183,7 +172,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean compileBunchOfSourceDirectories(
|
public static boolean compileBunchOfSourceDirectories(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
|
|
||||||
List<String> sources, String jar, String outputDir, boolean includeRuntime) {
|
List<String> sources, String jar, String outputDir, boolean includeRuntime) {
|
||||||
for (String source : sources) {
|
for (String source : sources) {
|
||||||
@@ -195,7 +184,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static ClassLoader compileText(
|
public static ClassLoader compileText(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
String code) {
|
String code) {
|
||||||
configuration.getEnvironment()
|
configuration.getEnvironment()
|
||||||
.addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code));
|
.addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code));
|
||||||
@@ -208,13 +197,13 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static GenerationState analyzeAndGenerate(CompileEnvironmentConfiguration configuration) {
|
public static GenerationState analyzeAndGenerate(K2JVMCompileEnvironmentConfiguration configuration) {
|
||||||
return analyzeAndGenerate(configuration, configuration.getCompilerDependencies().getCompilerSpecialMode().isStubs());
|
return analyzeAndGenerate(configuration, configuration.getEnvironment().getCompilerDependencies().getCompilerSpecialMode().isStubs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static GenerationState analyzeAndGenerate(
|
public static GenerationState analyzeAndGenerate(
|
||||||
CompileEnvironmentConfiguration configuration,
|
K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
boolean stubs
|
boolean stubs
|
||||||
) {
|
) {
|
||||||
AnalyzeExhaust exhaust = analyze(configuration, stubs);
|
AnalyzeExhaust exhaust = analyze(configuration, stubs);
|
||||||
@@ -230,7 +219,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static AnalyzeExhaust analyze(
|
private static AnalyzeExhaust analyze(
|
||||||
final CompileEnvironmentConfiguration configuration,
|
final K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
boolean stubs) {
|
boolean stubs) {
|
||||||
final JetCoreEnvironment environment = configuration.getEnvironment();
|
final JetCoreEnvironment environment = configuration.getEnvironment();
|
||||||
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(configuration.getMessageCollector());
|
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(configuration.getMessageCollector());
|
||||||
@@ -244,7 +233,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||||
environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely,
|
environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely,
|
||||||
JetControlFlowDataTraceFactory.EMPTY,
|
JetControlFlowDataTraceFactory.EMPTY,
|
||||||
configuration.getCompilerDependencies());
|
configuration.getEnvironment().getCompilerDependencies());
|
||||||
}
|
}
|
||||||
}, environment.getSourceFiles()
|
}, environment.getSourceFiles()
|
||||||
);
|
);
|
||||||
@@ -254,7 +243,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static GenerationState generate(
|
private static GenerationState generate(
|
||||||
final CompileEnvironmentConfiguration configuration,
|
final K2JVMCompileEnvironmentConfiguration configuration,
|
||||||
AnalyzeExhaust exhaust,
|
AnalyzeExhaust exhaust,
|
||||||
boolean stubs) {
|
boolean stubs) {
|
||||||
JetCoreEnvironment environment = configuration.getEnvironment();
|
JetCoreEnvironment environment = configuration.getEnvironment();
|
||||||
@@ -267,7 +256,7 @@ public class KotlinToJVMBytecodeCompiler {
|
|||||||
};
|
};
|
||||||
GenerationState generationState = new GenerationState(project, ClassBuilderFactories.binaries(stubs), backendProgress,
|
GenerationState generationState = new GenerationState(project, ClassBuilderFactories.binaries(stubs), backendProgress,
|
||||||
exhaust, environment.getSourceFiles(),
|
exhaust, environment.getSourceFiles(),
|
||||||
configuration.getCompilerDependencies().getCompilerSpecialMode());
|
configuration.getEnvironment().getCompilerDependencies().getCompilerSpecialMode());
|
||||||
generationState.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
|
generationState.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
|
||||||
|
|
||||||
List<CompilerPlugin> plugins = configuration.getCompilerPlugins();
|
List<CompilerPlugin> plugins = configuration.getCompilerPlugins();
|
||||||
|
|||||||
+1
@@ -24,6 +24,7 @@ public enum CompilerSpecialMode {
|
|||||||
BUILTINS,
|
BUILTINS,
|
||||||
JDK_HEADERS,
|
JDK_HEADERS,
|
||||||
STDLIB,
|
STDLIB,
|
||||||
|
JS
|
||||||
;
|
;
|
||||||
|
|
||||||
public boolean includeJdkHeaders() {
|
public boolean includeJdkHeaders() {
|
||||||
|
|||||||
+75
-48
@@ -92,11 +92,7 @@ import org.jetbrains.jet.lang.resolve.constants.NullValue;
|
|||||||
import org.jetbrains.jet.lang.resolve.constants.ShortValue;
|
import org.jetbrains.jet.lang.resolve.constants.ShortValue;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
import org.jetbrains.jet.lang.resolve.constants.StringValue;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
|
import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
|
import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
|
||||||
@@ -222,14 +218,14 @@ public class JavaDescriptorResolver {
|
|||||||
throw new IllegalStateException("both psiClass and psiPackage cannot be null");
|
throw new IllegalStateException("both psiClass and psiPackage cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fqName.lastSegmentIs(JvmAbi.PACKAGE_CLASS)) {
|
|
||||||
throw new IllegalStateException("identified cannot have last segment " + JvmAbi.PACKAGE_CLASS + ": " + fqName);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.staticMembers = staticMembers;
|
this.staticMembers = staticMembers;
|
||||||
this.kotlin = psiClass != null &&
|
this.kotlin = psiClass != null &&
|
||||||
(new PsiClassWrapper(psiClass).getJetClass().isDefined() || psiClass.getName().equals(JvmAbi.PACKAGE_CLASS));
|
(new PsiClassWrapper(psiClass).getJetClass().isDefined() || psiClass.getName().equals(JvmAbi.PACKAGE_CLASS));
|
||||||
classOrNamespaceDescriptor = descriptor;
|
classOrNamespaceDescriptor = descriptor;
|
||||||
|
|
||||||
|
if (fqName.lastSegmentIs(JvmAbi.PACKAGE_CLASS) && psiClass != null && kotlin) {
|
||||||
|
throw new IllegalStateException("Kotlin namespace cannot have last segment " + JvmAbi.PACKAGE_CLASS + ": " + fqName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ResolverScopeData(boolean negative) {
|
protected ResolverScopeData(boolean negative) {
|
||||||
@@ -356,6 +352,15 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ClassDescriptor resolveJavaLangObject() {
|
||||||
|
ClassDescriptor clazz = resolveClass(JdkNames.JL_OBJECT.getFqName(), DescriptorSearchRule.IGNORE_IF_FOUND_IN_KOTLIN);
|
||||||
|
if (clazz == null) {
|
||||||
|
// TODO: warning
|
||||||
|
}
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
|
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) {
|
||||||
List<Runnable> tasks = Lists.newArrayList();
|
List<Runnable> tasks = Lists.newArrayList();
|
||||||
@@ -466,7 +471,7 @@ public class JavaDescriptorResolver {
|
|||||||
"class " + psiClass.getQualifiedName());
|
"class " + psiClass.getQualifiedName());
|
||||||
|
|
||||||
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
|
// TODO: ugly hack: tests crash if initializeTypeParameters called with class containing proper supertypes
|
||||||
supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData.classDescriptor, classData.getTypeParameters()));
|
supertypes.addAll(getSupertypes(new PsiClassWrapper(psiClass), classData, classData.getTypeParameters()));
|
||||||
|
|
||||||
PsiMethod[] psiConstructors = psiClass.getConstructors();
|
PsiMethod[] psiConstructors = psiClass.getConstructors();
|
||||||
|
|
||||||
@@ -530,28 +535,7 @@ public class JavaDescriptorResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (PsiMethod psiConstructor : psiConstructors) {
|
for (PsiMethod psiConstructor : psiConstructors) {
|
||||||
PsiMethodWrapper constructor = new PsiMethodWrapper(psiConstructor);
|
resolveConstructor(psiClass, classData, isStatic, psiConstructor);
|
||||||
|
|
||||||
if (constructor.getJetConstructor().hidden()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
|
||||||
classData.classDescriptor,
|
|
||||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
|
||||||
false);
|
|
||||||
String context = "constructor of class " + psiClass.getQualifiedName();
|
|
||||||
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor,
|
|
||||||
constructor.getParameters(),
|
|
||||||
TypeVariableResolvers.classTypeVariableResolver(classData.classDescriptor, context));
|
|
||||||
if (valueParameterDescriptors.receiverType != null) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
constructorDescriptor.initialize(typeParameters, valueParameterDescriptors.descriptors,
|
|
||||||
resolveVisibilityFromPsiModifiers(psiConstructor), isStatic);
|
|
||||||
constructorDescriptor.setReturnType(classData.classDescriptor.getDefaultType());
|
|
||||||
classData.classDescriptor.addConstructor(constructorDescriptor, null);
|
|
||||||
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,6 +549,32 @@ public class JavaDescriptorResolver {
|
|||||||
return classData;
|
return classData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resolveConstructor(PsiClass psiClass, ResolverBinaryClassData classData, boolean aStatic, PsiMethod psiConstructor) {
|
||||||
|
PsiMethodWrapper constructor = new PsiMethodWrapper(psiConstructor);
|
||||||
|
|
||||||
|
if (constructor.getJetConstructor().hidden()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl(
|
||||||
|
classData.classDescriptor,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||||
|
false);
|
||||||
|
String context = "constructor of class " + psiClass.getQualifiedName();
|
||||||
|
ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor,
|
||||||
|
constructor.getParameters(),
|
||||||
|
TypeVariableResolvers.classTypeVariableResolver(classData.classDescriptor, context));
|
||||||
|
if (valueParameterDescriptors.receiverType != null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
constructorDescriptor.initialize(classData.classDescriptor.getTypeConstructor().getParameters(),
|
||||||
|
valueParameterDescriptors.descriptors,
|
||||||
|
resolveVisibilityFromPsiModifiers(psiConstructor), aStatic);
|
||||||
|
constructorDescriptor.setReturnType(classData.classDescriptor.getDefaultType());
|
||||||
|
classData.classDescriptor.addConstructor(constructorDescriptor, null);
|
||||||
|
trace.record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
static void checkPsiClassIsNotJet(PsiClass psiClass) {
|
||||||
if (psiClass instanceof JetJavaMirrorMarker) {
|
if (psiClass instanceof JetJavaMirrorMarker) {
|
||||||
throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass.getQualifiedName());
|
throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass.getQualifiedName());
|
||||||
@@ -599,7 +609,7 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
classDescriptorCache.put(fqName, classData);
|
classDescriptorCache.put(fqName, classData);
|
||||||
|
|
||||||
classData.classDescriptor.setSupertypes(getSupertypes(new PsiClassWrapper(classObjectPsiClass), classData.classDescriptor, new ArrayList<TypeParameterDescriptor>(0)));
|
classData.classDescriptor.setSupertypes(getSupertypes(new PsiClassWrapper(classObjectPsiClass), classData, new ArrayList<TypeParameterDescriptor>(0)));
|
||||||
classData.classDescriptor.setName(JetPsiUtil.NO_NAME_PROVIDED); // TODO
|
classData.classDescriptor.setName(JetPsiUtil.NO_NAME_PROVIDED); // TODO
|
||||||
classData.classDescriptor.setModality(Modality.FINAL);
|
classData.classDescriptor.setModality(Modality.FINAL);
|
||||||
classData.classDescriptor.setVisibility(containing.getVisibility());
|
classData.classDescriptor.setVisibility(containing.getVisibility());
|
||||||
@@ -855,14 +865,22 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
private void initializeTypeParameters(List<TypeParameterDescriptorInitialization> typeParametersInitialization, @NotNull DeclarationDescriptor typeParametersOwner, @NotNull String context) {
|
private void initializeTypeParameters(List<TypeParameterDescriptorInitialization> typeParametersInitialization, @NotNull DeclarationDescriptor typeParametersOwner, @NotNull String context) {
|
||||||
List<TypeParameterDescriptor> prevTypeParameters = new ArrayList<TypeParameterDescriptor>();
|
List<TypeParameterDescriptor> prevTypeParameters = new ArrayList<TypeParameterDescriptor>();
|
||||||
|
|
||||||
|
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
|
||||||
|
for (TypeParameterDescriptorInitialization typeParameterDescriptor : typeParametersInitialization) {
|
||||||
|
typeParameters.add(typeParameterDescriptor.descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
for (TypeParameterDescriptorInitialization psiTypeParameter : typeParametersInitialization) {
|
for (TypeParameterDescriptorInitialization psiTypeParameter : typeParametersInitialization) {
|
||||||
prevTypeParameters.add(psiTypeParameter.descriptor);
|
prevTypeParameters.add(psiTypeParameter.descriptor);
|
||||||
initializeTypeParameter(psiTypeParameter,
|
initializeTypeParameter(psiTypeParameter,
|
||||||
TypeVariableResolvers.typeVariableResolverFromTypeParameters(prevTypeParameters, typeParametersOwner, context));
|
TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, typeParametersOwner, context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<JetType> getSupertypes(PsiClassWrapper psiClass, ClassDescriptor classDescriptor, List<TypeParameterDescriptor> typeParameters) {
|
private Collection<JetType> getSupertypes(PsiClassWrapper psiClass, ResolverBinaryClassData classData, List<TypeParameterDescriptor> typeParameters) {
|
||||||
|
ClassDescriptor classDescriptor = classData.classDescriptor;
|
||||||
|
|
||||||
final List<JetType> result = new ArrayList<JetType>();
|
final List<JetType> result = new ArrayList<JetType>();
|
||||||
|
|
||||||
String context = "class " + psiClass.getQualifiedName();
|
String context = "class " + psiClass.getQualifiedName();
|
||||||
@@ -908,7 +926,21 @@ public class JavaDescriptorResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result.isEmpty()) {
|
if (result.isEmpty()) {
|
||||||
result.add(JetStandardClasses.getAnyType());
|
if (classData.kotlin
|
||||||
|
|| psiClass.getQualifiedName().equals(JdkNames.JL_OBJECT.getFqName().getFqName())
|
||||||
|
// TODO: annotations
|
||||||
|
|| classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
|
||||||
|
result.add(JetStandardClasses.getAnyType());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ClassDescriptor object = resolveJavaLangObject();
|
||||||
|
if (object != null) {
|
||||||
|
result.add(object.getDefaultType());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.add(JetStandardClasses.getAnyType());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -923,7 +955,7 @@ public class JavaDescriptorResolver {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType transform = semanticServices.getTypeTransformer().transformToType(type, typeVariableResolver);
|
JetType transform = semanticServices.getTypeTransformer().transformToType(type, JavaTypeTransformer.TypeUsage.SUPERTYPE, typeVariableResolver);
|
||||||
|
|
||||||
result.add(TypeUtils.makeNotNullable(transform));
|
result.add(TypeUtils.makeNotNullable(transform));
|
||||||
}
|
}
|
||||||
@@ -1120,7 +1152,7 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
JetType varargElementType;
|
JetType varargElementType;
|
||||||
if (psiType instanceof PsiEllipsisType) {
|
if (psiType instanceof PsiEllipsisType) {
|
||||||
varargElementType = JetStandardLibrary.getInstance().getArrayElementType(outType);
|
varargElementType = JetStandardLibrary.getInstance().getArrayElementType(TypeUtils.makeNotNullable(outType));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
varargElementType = null;
|
varargElementType = null;
|
||||||
@@ -1239,8 +1271,6 @@ public class JavaDescriptorResolver {
|
|||||||
namedMembers.propertyAccessors = Collections.emptyList();
|
namedMembers.propertyAccessors = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeVariableResolver typeVariableResolver = TypeVariableResolvers.classTypeVariableResolver(owner, context);
|
|
||||||
|
|
||||||
class GroupingValue {
|
class GroupingValue {
|
||||||
PropertyAccessorData getter;
|
PropertyAccessorData getter;
|
||||||
PropertyAccessorData setter;
|
PropertyAccessorData setter;
|
||||||
@@ -1381,14 +1411,14 @@ public class JavaDescriptorResolver {
|
|||||||
PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember();
|
PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember();
|
||||||
|
|
||||||
if (anyMember == members.setter) {
|
if (anyMember == members.setter) {
|
||||||
typeParameters = resolveMethodTypeParameters(method, propertyDescriptor, typeVariableResolver);
|
typeParameters = resolveMethodTypeParameters(method, propertyDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (members.getter != null) {
|
if (members.getter != null) {
|
||||||
PsiMethodWrapper method = (PsiMethodWrapper) members.getter.getMember();
|
PsiMethodWrapper method = (PsiMethodWrapper) members.getter.getMember();
|
||||||
|
|
||||||
if (anyMember == members.getter) {
|
if (anyMember == members.getter) {
|
||||||
typeParameters = resolveMethodTypeParameters(method, propertyDescriptor, typeVariableResolver);
|
typeParameters = resolveMethodTypeParameters(method, propertyDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1549,7 +1579,7 @@ public class JavaDescriptorResolver {
|
|||||||
private TypeSubstitutor createSubstitutorForGenericSupertypes(@Nullable ClassDescriptor classDescriptor) {
|
private TypeSubstitutor createSubstitutorForGenericSupertypes(@Nullable ClassDescriptor classDescriptor) {
|
||||||
TypeSubstitutor typeSubstitutor;
|
TypeSubstitutor typeSubstitutor;
|
||||||
if (classDescriptor != null) {
|
if (classDescriptor != null) {
|
||||||
typeSubstitutor = TypeUtils.buildDeepSubstitutor(classDescriptor.getDefaultType());
|
typeSubstitutor = SubstitutionUtils.buildDeepSubstitutor(classDescriptor.getDefaultType());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typeSubstitutor = TypeSubstitutor.EMPTY;
|
typeSubstitutor = TypeSubstitutor.EMPTY;
|
||||||
@@ -1617,9 +1647,7 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName();
|
String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName();
|
||||||
|
|
||||||
final TypeVariableResolver typeVariableResolverForParameters = TypeVariableResolvers.classTypeVariableResolver(scopeData.classOrNamespaceDescriptor, context);
|
final List<TypeParameterDescriptor> methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl);
|
||||||
|
|
||||||
final List<TypeParameterDescriptor> methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl, typeVariableResolverForParameters);
|
|
||||||
|
|
||||||
TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters, functionDescriptorImpl, context);
|
TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters, functionDescriptorImpl, context);
|
||||||
|
|
||||||
@@ -1760,8 +1788,7 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
private List<TypeParameterDescriptor> resolveMethodTypeParameters(
|
private List<TypeParameterDescriptor> resolveMethodTypeParameters(
|
||||||
@NotNull PsiMethodWrapper method,
|
@NotNull PsiMethodWrapper method,
|
||||||
@NotNull DeclarationDescriptor functionDescriptor,
|
@NotNull DeclarationDescriptor functionDescriptor) {
|
||||||
@NotNull TypeVariableResolver classTypeVariableResolver) {
|
|
||||||
|
|
||||||
List<TypeParameterDescriptorInitialization> typeParametersIntialization;
|
List<TypeParameterDescriptorInitialization> typeParametersIntialization;
|
||||||
if (method.getJetMethod().typeParameters().length() > 0) {
|
if (method.getJetMethod().typeParameters().length() > 0) {
|
||||||
|
|||||||
+43
-20
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.lang.resolve.java;
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -25,16 +26,16 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.FqName;
|
import org.jetbrains.jet.lang.resolve.FqName;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureReader;
|
import org.jetbrains.jet.rt.signature.JetSignatureReader;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import static org.jetbrains.jet.lang.resolve.java.JavaTypeTransformer.TypeUsage.*;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -63,9 +64,11 @@ public class JavaTypeTransformer {
|
|||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TypeProjection transformToTypeProjection(@NotNull final PsiType javaType,
|
private TypeProjection transformToTypeProjection(@NotNull final PsiType javaType,
|
||||||
@NotNull final TypeParameterDescriptor typeParameterDescriptor,
|
@NotNull final TypeParameterDescriptor typeParameterDescriptor,
|
||||||
@NotNull final TypeVariableResolver typeVariableByPsiResolver) {
|
@NotNull final TypeVariableResolver typeVariableByPsiResolver,
|
||||||
|
@NotNull final TypeUsage howThisTypeIsUsed
|
||||||
|
) {
|
||||||
TypeProjection result = javaType.accept(new PsiTypeVisitor<TypeProjection>() {
|
TypeProjection result = javaType.accept(new PsiTypeVisitor<TypeProjection>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,18 +79,18 @@ public class JavaTypeTransformer {
|
|||||||
@Override
|
@Override
|
||||||
public TypeProjection visitWildcardType(PsiWildcardType wildcardType) {
|
public TypeProjection visitWildcardType(PsiWildcardType wildcardType) {
|
||||||
if (!wildcardType.isBounded()) {
|
if (!wildcardType.isBounded()) {
|
||||||
return TypeUtils.makeStarProjection(typeParameterDescriptor);
|
return SubstitutionUtils.makeStarProjection(typeParameterDescriptor);
|
||||||
}
|
}
|
||||||
Variance variance = wildcardType.isExtends() ? Variance.OUT_VARIANCE : Variance.IN_VARIANCE;
|
Variance variance = wildcardType.isExtends() ? Variance.OUT_VARIANCE : Variance.IN_VARIANCE;
|
||||||
|
|
||||||
PsiType bound = wildcardType.getBound();
|
PsiType bound = wildcardType.getBound();
|
||||||
assert bound != null;
|
assert bound != null;
|
||||||
return new TypeProjection(variance, transformToType(bound, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver));
|
return new TypeProjection(variance, transformToType(bound, UPPER_BOUND, typeVariableByPsiResolver));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeProjection visitType(PsiType type) {
|
public TypeProjection visitType(PsiType type) {
|
||||||
return new TypeProjection(transformToType(type, TypeUsage.TYPE_ARGUMENT, typeVariableByPsiResolver));
|
return new TypeProjection(transformToType(type, howThisTypeIsUsed, typeVariableByPsiResolver));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
@@ -126,22 +129,39 @@ public class JavaTypeTransformer {
|
|||||||
|
|
||||||
if (psiClass instanceof PsiTypeParameter) {
|
if (psiClass instanceof PsiTypeParameter) {
|
||||||
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
|
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
|
||||||
|
|
||||||
|
PsiTypeParameterListOwner typeParameterListOwner = typeParameter.getOwner();
|
||||||
|
if (typeParameterListOwner instanceof PsiMethod) {
|
||||||
|
PsiMethod psiMethod = (PsiMethod) typeParameterListOwner;
|
||||||
|
if (psiMethod.isConstructor()) {
|
||||||
|
Set<JetType> supertypesJet = Sets.newHashSet();
|
||||||
|
for (PsiClassType supertype : typeParameter.getExtendsListTypes()) {
|
||||||
|
supertypesJet.add(transformToType(supertype, UPPER_BOUND, typeVariableResolver));
|
||||||
|
}
|
||||||
|
return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName());
|
TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName());
|
||||||
|
|
||||||
if (howThisTypeIsUsed == TypeUsage.TYPE_ARGUMENT || howThisTypeIsUsed == TypeUsage.UPPER_BOUND) {
|
// In Java: ArrayList<T>
|
||||||
// In Java: ArrayList<T>
|
// In Kotlin: ArrayList<T>, not ArrayList<T?>
|
||||||
// In Kotlin: ArrayList<T>, not ArrayList<T?>
|
// nullability will be taken care of in individual member signatures
|
||||||
// nullability will be taken care of in individual member signatures
|
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed);
|
||||||
return typeParameterDescriptor.getDefaultType();
|
if (nullable) {
|
||||||
|
return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType());
|
return typeParameterDescriptor.getDefaultType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?>
|
||||||
|
boolean nullable = !EnumSet.of(SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed);
|
||||||
|
|
||||||
JetType jetAnalog = getKotlinAnalog(new FqName(psiClass.getQualifiedName()));
|
JetType jetAnalog = getKotlinAnalog(new FqName(psiClass.getQualifiedName()));
|
||||||
if (jetAnalog != null) {
|
if (jetAnalog != null) {
|
||||||
return jetAnalog;
|
return TypeUtils.makeNullableAsSpecified(jetAnalog, nullable);
|
||||||
}
|
}
|
||||||
|
|
||||||
final ClassDescriptor classData =
|
final ClassDescriptor classData =
|
||||||
@@ -154,7 +174,7 @@ public class JavaTypeTransformer {
|
|||||||
if (classType.isRaw()) {
|
if (classType.isRaw()) {
|
||||||
List<TypeParameterDescriptor> parameters = classData.getTypeConstructor().getParameters();
|
List<TypeParameterDescriptor> parameters = classData.getTypeConstructor().getParameters();
|
||||||
for (TypeParameterDescriptor parameter : parameters) {
|
for (TypeParameterDescriptor parameter : parameters) {
|
||||||
arguments.add(TypeUtils.makeStarProjection(parameter));
|
arguments.add(SubstitutionUtils.makeStarProjection(parameter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -171,13 +191,15 @@ public class JavaTypeTransformer {
|
|||||||
PsiType psiArgument = psiArguments[i];
|
PsiType psiArgument = psiArguments[i];
|
||||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||||
|
|
||||||
arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor, typeVariableResolver));
|
TypeUsage howTheProjectionIsUsed = howThisTypeIsUsed == SUPERTYPE ? SUPERTYPE_ARGUMENT : TYPE_ARGUMENT;
|
||||||
|
arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor, typeVariableResolver, howTheProjectionIsUsed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JetTypeImpl(
|
return new JetTypeImpl(
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
classData.getTypeConstructor(),
|
classData.getTypeConstructor(),
|
||||||
true,
|
nullable,
|
||||||
arguments,
|
arguments,
|
||||||
classData.getMemberScope(arguments));
|
classData.getMemberScope(arguments));
|
||||||
}
|
}
|
||||||
@@ -275,6 +297,7 @@ public class JavaTypeTransformer {
|
|||||||
MEMBER_SIGNATURE_COVARIANT,
|
MEMBER_SIGNATURE_COVARIANT,
|
||||||
MEMBER_SIGNATURE_CONTRAVARIANT,
|
MEMBER_SIGNATURE_CONTRAVARIANT,
|
||||||
MEMBER_SIGNATURE_INVARIANT,
|
MEMBER_SIGNATURE_INVARIANT,
|
||||||
SUPERTYPE
|
SUPERTYPE,
|
||||||
|
SUPERTYPE_ARGUMENT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.java;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
public class JdkNames {
|
||||||
|
|
||||||
|
public static final JvmClassName JL_OBJECT = new JvmClassName("java.lang.Object");
|
||||||
|
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ import org.jetbrains.jet.plugin.JetMainDetector;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.MUST_BE_WRAPPED_IN_A_REF;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE;
|
||||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -599,7 +599,7 @@ public class JetFlowInformationProvider {
|
|||||||
!DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return;
|
!DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return;
|
||||||
VariableStatus variableStatus = enterData.get(variableDescriptor);
|
VariableStatus variableStatus = enterData.get(variableDescriptor);
|
||||||
if (instruction instanceof WriteValueInstruction) {
|
if (instruction instanceof WriteValueInstruction) {
|
||||||
if (trace.get(MUST_BE_WRAPPED_IN_A_REF, variableDescriptor)) return;
|
if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return;
|
||||||
JetElement element = ((WriteValueInstruction) instruction).getElement();
|
JetElement element = ((WriteValueInstruction) instruction).getElement();
|
||||||
if (variableStatus != VariableStatus.READ) {
|
if (variableStatus != VariableStatus.READ) {
|
||||||
if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) {
|
if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) {
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
|||||||
if (typeConstructor.getParameters().isEmpty()) {
|
if (typeConstructor.getParameters().isEmpty()) {
|
||||||
return memberDeclarations;
|
return memberDeclarations;
|
||||||
}
|
}
|
||||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
|
Map<TypeConstructor, TypeProjection> substitutionContext = SubstitutionUtils
|
||||||
|
.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
|
||||||
return new SubstitutingScope(memberDeclarations, TypeSubstitutor.create(substitutionContext));
|
return new SubstitutingScope(memberDeclarations, TypeSubstitutor.create(substitutionContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
||||||
@@ -47,7 +48,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i
|
|||||||
|
|
||||||
protected Modality modality;
|
protected Modality modality;
|
||||||
protected Visibility visibility;
|
protected Visibility visibility;
|
||||||
protected final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet();
|
protected final Set<FunctionDescriptor> overriddenFunctions = Sets.newLinkedHashSet(); // LinkedHashSet is essential here
|
||||||
private final FunctionDescriptor original;
|
private final FunctionDescriptor original;
|
||||||
private final Kind kind;
|
private final Kind kind;
|
||||||
|
|
||||||
@@ -230,7 +231,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i
|
|||||||
);
|
);
|
||||||
if (copyOverrides) {
|
if (copyOverrides) {
|
||||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||||
substitutedDescriptor.addOverriddenDescriptor(overriddenFunction.substitute(substitutor));
|
OverridingUtil.bindOverride(substitutedDescriptor, overriddenFunction.substitute(substitutor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return substitutedDescriptor;
|
return substitutedDescriptor;
|
||||||
|
|||||||
+15
-3
@@ -119,18 +119,30 @@ public class FunctionDescriptorUtil {
|
|||||||
return parameterScope;
|
return parameterScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initializeFromFunctionType(@NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType, @NotNull ReceiverDescriptor expectedThisObject) {
|
public static void initializeFromFunctionType(@NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType, @NotNull ReceiverDescriptor expectedThisObject,
|
||||||
|
@NotNull Modality modality, @NotNull Visibility visibility) {
|
||||||
|
|
||||||
assert JetStandardClasses.isFunctionType(functionType);
|
assert JetStandardClasses.isFunctionType(functionType);
|
||||||
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
|
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
|
||||||
expectedThisObject,
|
expectedThisObject,
|
||||||
Collections.<TypeParameterDescriptor>emptyList(),
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
|
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
|
||||||
JetStandardClasses.getReturnTypeFromFunctionType(functionType),
|
JetStandardClasses.getReturnTypeFromFunctionType(functionType),
|
||||||
Modality.FINAL,
|
modality,
|
||||||
Visibilities.LOCAL);
|
visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
|
public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
|
||||||
return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
|
return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FunctionDescriptor getInvokeFunction(@NotNull JetType functionType) {
|
||||||
|
assert JetStandardClasses.isFunctionType(functionType);
|
||||||
|
|
||||||
|
ClassifierDescriptor classDescriptorForFunction = functionType.getConstructor().getDeclarationDescriptor();
|
||||||
|
assert classDescriptorForFunction instanceof ClassDescriptor;
|
||||||
|
Set<FunctionDescriptor> invokeFunctions = ((ClassDescriptor) classDescriptorForFunction).getMemberScope(functionType.getArguments()).getFunctions("invoke");
|
||||||
|
assert invokeFunctions.size() == 1;
|
||||||
|
return invokeFunctions.iterator().next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-5
@@ -33,7 +33,8 @@ import java.util.Set;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class MutableClassDescriptor extends MutableClassDescriptorLite {
|
public class MutableClassDescriptor extends MutableClassDescriptorLite {
|
||||||
private final Set<CallableMemberDescriptor> callableMembers = Sets.newHashSet();
|
private final Set<CallableMemberDescriptor> declaredCallableMembers = Sets.newHashSet();
|
||||||
|
private final Set<CallableMemberDescriptor> allCallableMembers = Sets.newHashSet(); // includes fake overrides
|
||||||
private final Set<PropertyDescriptor> properties = Sets.newHashSet();
|
private final Set<PropertyDescriptor> properties = Sets.newHashSet();
|
||||||
private final Set<SimpleFunctionDescriptor> functions = Sets.newHashSet();
|
private final Set<SimpleFunctionDescriptor> functions = Sets.newHashSet();
|
||||||
|
|
||||||
@@ -104,7 +105,10 @@ public class MutableClassDescriptor extends MutableClassDescriptorLite {
|
|||||||
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
super.addPropertyDescriptor(propertyDescriptor);
|
super.addPropertyDescriptor(propertyDescriptor);
|
||||||
properties.add(propertyDescriptor);
|
properties.add(propertyDescriptor);
|
||||||
callableMembers.add(propertyDescriptor);
|
if (propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
|
declaredCallableMembers.add(propertyDescriptor);
|
||||||
|
}
|
||||||
|
allCallableMembers.add(propertyDescriptor);
|
||||||
scopeForMemberResolution.addPropertyDescriptor(propertyDescriptor);
|
scopeForMemberResolution.addPropertyDescriptor(propertyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +116,10 @@ public class MutableClassDescriptor extends MutableClassDescriptorLite {
|
|||||||
public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
|
public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
|
||||||
super.addFunctionDescriptor(functionDescriptor);
|
super.addFunctionDescriptor(functionDescriptor);
|
||||||
functions.add(functionDescriptor);
|
functions.add(functionDescriptor);
|
||||||
callableMembers.add(functionDescriptor);
|
if (functionDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
|
declaredCallableMembers.add(functionDescriptor);
|
||||||
|
}
|
||||||
|
allCallableMembers.add(functionDescriptor);
|
||||||
scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
|
scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,8 +134,13 @@ public class MutableClassDescriptor extends MutableClassDescriptorLite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Set<CallableMemberDescriptor> getCallableMembers() {
|
public Set<CallableMemberDescriptor> getDeclaredCallableMembers() {
|
||||||
return callableMembers;
|
return declaredCallableMembers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Set<CallableMemberDescriptor> getAllCallableMembers() {
|
||||||
|
return allCallableMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-2
@@ -127,7 +127,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WritableScope getScopeForMemberLookupAsWritableScope() {
|
private WritableScope getScopeForMemberLookupAsWritableScope() {
|
||||||
// hack
|
// hack
|
||||||
return (WritableScope) scopeForMemberLookup;
|
return (WritableScope) scopeForMemberLookup;
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp
|
|||||||
if (typeArguments.isEmpty()) return scopeForMemberLookup;
|
if (typeArguments.isEmpty()) return scopeForMemberLookup;
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
|
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
|
||||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeParameters, typeArguments);
|
Map<TypeConstructor, TypeProjection> substitutionContext = SubstitutionUtils.buildSubstitutionContext(typeParameters, typeArguments);
|
||||||
return new SubstitutingScope(scopeForMemberLookup, TypeSubstitutor.create(substitutionContext));
|
return new SubstitutingScope(scopeForMemberLookup, TypeSubstitutor.create(substitutionContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
||||||
@@ -42,7 +43,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
private Visibility visibility;
|
private Visibility visibility;
|
||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
private final boolean isObject;
|
private final boolean isObject;
|
||||||
private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet();
|
private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet(); // LinkedHashSet is essential here
|
||||||
private final PropertyDescriptor original;
|
private final PropertyDescriptor original;
|
||||||
private final Kind kind;
|
private final Kind kind;
|
||||||
|
|
||||||
@@ -268,7 +269,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
|
|
||||||
if (copyOverrides) {
|
if (copyOverrides) {
|
||||||
for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
|
for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
|
||||||
substitutedDescriptor.addOverriddenDescriptor(propertyDescriptor.substitute(substitutor));
|
OverridingUtil.bindOverride(substitutedDescriptor, propertyDescriptor.substitute(substitutor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-1
@@ -21,6 +21,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
@@ -31,8 +33,22 @@ public interface ValueParameterDescriptor extends VariableDescriptor, Annotated
|
|||||||
* @return the parameter index
|
* @return the parameter index
|
||||||
*/
|
*/
|
||||||
int getIndex();
|
int getIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The font-end relies on this property when resolving function calls
|
||||||
|
*
|
||||||
|
* @return {@code true} iff the parameter has a default value, i.e. declares it or inherits
|
||||||
|
* by overriding a parameter in an overridden function.
|
||||||
|
*/
|
||||||
boolean hasDefaultValue();
|
boolean hasDefaultValue();
|
||||||
boolean isRef();
|
|
||||||
|
/**
|
||||||
|
* The back-end should relies on this property when generating function signatures
|
||||||
|
*
|
||||||
|
* @return {@code true} iff the parameter declares a default value, i.e. explicitly specifies it in the function header
|
||||||
|
*/
|
||||||
|
boolean declaresDefaultValue();
|
||||||
|
|
||||||
@Nullable JetType getVarargElementType();
|
@Nullable JetType getVarargElementType();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,4 +62,14 @@ public interface ValueParameterDescriptor extends VariableDescriptor, Annotated
|
|||||||
@NotNull
|
@NotNull
|
||||||
ValueParameterDescriptor copy(DeclarationDescriptor newOwner);
|
ValueParameterDescriptor copy(DeclarationDescriptor newOwner);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter p1 overrides p2 iff
|
||||||
|
* a) their respective owners (function declarations) f1 override f2
|
||||||
|
* b) p1 and p2 have the same indices in the owners' parameter lists
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
Set<? extends ValueParameterDescriptor> getOverriddenDescriptors();
|
||||||
|
|
||||||
|
void addOverriddenDescriptor(@NotNull ValueParameterDescriptor overridden);
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-7
@@ -17,24 +17,33 @@
|
|||||||
package org.jetbrains.jet.lang.descriptors;
|
package org.jetbrains.jet.lang.descriptors;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
|
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
|
||||||
private final boolean hasDefaultValue;
|
private Boolean hasDefaultValue;
|
||||||
|
private final boolean declaresDefaultValue;
|
||||||
|
|
||||||
private final JetType varargElementType;
|
private final JetType varargElementType;
|
||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
private final int index;
|
private final int index;
|
||||||
private final ValueParameterDescriptor original;
|
private final ValueParameterDescriptor original;
|
||||||
|
|
||||||
|
private final Set<ValueParameterDescriptor> overriddenDescriptors = Sets.newLinkedHashSet(); // Linked is essential
|
||||||
|
private boolean overriddenDescriptorsLocked = false;
|
||||||
|
private final Set<? extends ValueParameterDescriptor> readOnlyOverriddenDescriptors = Collections.unmodifiableSet(overriddenDescriptors);
|
||||||
|
|
||||||
public ValueParameterDescriptorImpl(
|
public ValueParameterDescriptorImpl(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
int index,
|
int index,
|
||||||
@@ -42,12 +51,12 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
boolean isVar,
|
boolean isVar,
|
||||||
@NotNull JetType outType,
|
@NotNull JetType outType,
|
||||||
boolean hasDefaultValue,
|
boolean declaresDefaultValue,
|
||||||
@Nullable JetType varargElementType) {
|
@Nullable JetType varargElementType) {
|
||||||
super(containingDeclaration, annotations, name, outType);
|
super(containingDeclaration, annotations, name, outType);
|
||||||
this.original = this;
|
this.original = this;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.hasDefaultValue = hasDefaultValue;
|
this.declaresDefaultValue = declaresDefaultValue;
|
||||||
this.varargElementType = varargElementType;
|
this.varargElementType = varargElementType;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
}
|
}
|
||||||
@@ -59,11 +68,11 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
boolean isVar,
|
boolean isVar,
|
||||||
@NotNull JetType outType,
|
@NotNull JetType outType,
|
||||||
@Nullable JetType varargElementType
|
@Nullable JetType varargElementType
|
||||||
) {
|
) {
|
||||||
super(containingDeclaration, annotations, original.getName(), outType);
|
super(containingDeclaration, annotations, original.getName(), outType);
|
||||||
this.original = original;
|
this.original = original;
|
||||||
this.index = original.getIndex();
|
this.index = original.getIndex();
|
||||||
this.hasDefaultValue = original.hasDefaultValue();
|
this.declaresDefaultValue = original.declaresDefaultValue();
|
||||||
this.varargElementType = varargElementType;
|
this.varargElementType = varargElementType;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
}
|
}
|
||||||
@@ -80,12 +89,30 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasDefaultValue() {
|
public boolean hasDefaultValue() {
|
||||||
|
computeDefaultValuePresence();
|
||||||
return hasDefaultValue;
|
return hasDefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRef() {
|
public boolean declaresDefaultValue() {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
return declaresDefaultValue && ((CallableMemberDescriptor) getContainingDeclaration()).getKind().isReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeDefaultValuePresence() {
|
||||||
|
if (hasDefaultValue != null) return;
|
||||||
|
overriddenDescriptorsLocked = true;
|
||||||
|
if (declaresDefaultValue) {
|
||||||
|
hasDefaultValue = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (ValueParameterDescriptor descriptor : overriddenDescriptors) {
|
||||||
|
if (descriptor.hasDefaultValue()) {
|
||||||
|
hasDefaultValue = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasDefaultValue = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -131,4 +158,17 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
public Visibility getVisibility() {
|
public Visibility getVisibility() {
|
||||||
return Visibilities.LOCAL;
|
return Visibilities.LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<? extends ValueParameterDescriptor> getOverriddenDescriptors() {
|
||||||
|
return readOnlyOverriddenDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOverriddenDescriptor(@NotNull ValueParameterDescriptor overridden) {
|
||||||
|
assert !overriddenDescriptorsLocked : "Adding more overridden descriptors is not allowed at this point: " +
|
||||||
|
"the presence of the default value has already been calculated";
|
||||||
|
overriddenDescriptors.add(overridden);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-58
@@ -1,58 +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.lang.descriptors;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author abreslav
|
|
||||||
*/
|
|
||||||
public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
|
|
||||||
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
|
|
||||||
JetType outType = variableDescriptor.getType();
|
|
||||||
assert outType != null;
|
|
||||||
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
|
|
||||||
FunctionDescriptorUtil.initializeFromFunctionType(result, outType, variableDescriptor.getExpectedThisObject());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final VariableDescriptor variableDescriptor;
|
|
||||||
|
|
||||||
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
|
|
||||||
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName(), Kind.DECLARATION);
|
|
||||||
this.variableDescriptor = variableDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VariableDescriptor getVariableDescriptor() {
|
|
||||||
return variableDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public VariableAsFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) {
|
|
||||||
throw new UnsupportedOperationException("Should not be copied for overriding");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -51,7 +51,7 @@ public interface Errors {
|
|||||||
//Elements with "INVISIBLE_REFERENCE" error are marked as unresolved, unlike elements with "INVISIBLE_MEMBER" error
|
//Elements with "INVISIBLE_REFERENCE" error are marked as unresolved, unlike elements with "INVISIBLE_MEMBER" error
|
||||||
DiagnosticFactory2<JetSimpleNameExpression, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_REFERENCE =
|
DiagnosticFactory2<JetSimpleNameExpression, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_REFERENCE =
|
||||||
DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory2<PsiElement, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<PsiElement, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory2.create(ERROR, PositioningStrategies.CALL_ELEMENT);
|
||||||
|
|
||||||
RedeclarationDiagnosticFactory REDECLARATION = new RedeclarationDiagnosticFactory(ERROR);
|
RedeclarationDiagnosticFactory REDECLARATION = new RedeclarationDiagnosticFactory(ERROR);
|
||||||
RedeclarationDiagnosticFactory NAME_SHADOWING = new RedeclarationDiagnosticFactory(WARNING);
|
RedeclarationDiagnosticFactory NAME_SHADOWING = new RedeclarationDiagnosticFactory(WARNING);
|
||||||
@@ -247,12 +247,12 @@ public interface Errors {
|
|||||||
public List<TextRange> mark(@NotNull JetDeclarationWithBody element) {
|
public List<TextRange> mark(@NotNull JetDeclarationWithBody element) {
|
||||||
JetExpression bodyExpression = element.getBodyExpression();
|
JetExpression bodyExpression = element.getBodyExpression();
|
||||||
if (!(bodyExpression instanceof JetBlockExpression)) {
|
if (!(bodyExpression instanceof JetBlockExpression)) {
|
||||||
return Collections.emptyList();
|
return markElement(element);
|
||||||
}
|
}
|
||||||
JetBlockExpression blockExpression = (JetBlockExpression)bodyExpression;
|
JetBlockExpression blockExpression = (JetBlockExpression)bodyExpression;
|
||||||
TextRange lastBracketRange = blockExpression.getLastBracketRange();
|
TextRange lastBracketRange = blockExpression.getLastBracketRange();
|
||||||
if (lastBracketRange == null) {
|
if (lastBracketRange == null) {
|
||||||
return Collections.emptyList();
|
return markElement(element);
|
||||||
}
|
}
|
||||||
return markRange(lastBracketRange);
|
return markRange(lastBracketRange);
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,6 @@ public interface Errors {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<TextRange> mark(@NotNull JetWhenExpression element) {
|
public List<TextRange> mark(@NotNull JetWhenExpression element) {
|
||||||
if (hasSyntaxError(element)) return Collections.emptyList();
|
|
||||||
return markElement(element.getWhenKeywordElement());
|
return markElement(element.getWhenKeywordElement());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -380,6 +379,12 @@ public interface Errors {
|
|||||||
DiagnosticFactory2<PsiElement, JetClassOrObject, CallableMemberDescriptor> MANY_IMPL_MEMBER_NOT_IMPLEMENTED =
|
DiagnosticFactory2<PsiElement, JetClassOrObject, CallableMemberDescriptor> MANY_IMPL_MEMBER_NOT_IMPLEMENTED =
|
||||||
DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2.create(ERROR);
|
||||||
|
|
||||||
|
SimpleDiagnosticFactory<JetParameter> DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE = SimpleDiagnosticFactory.create(ERROR, PositioningStrategies.PARAMETER_DEFAULT_VALUE);
|
||||||
|
DiagnosticFactory1<JetParameter, ValueParameterDescriptor> MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES = DiagnosticFactory1.create(ERROR, PositioningStrategies.POSITION_NAME_IDENTIFIER);
|
||||||
|
DiagnosticFactory1<JetClassOrObject, ValueParameterDescriptor> MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE = DiagnosticFactory1.create(ERROR, PositioningStrategies.POSITION_NAME_IDENTIFIER);
|
||||||
|
DiagnosticFactory2<JetParameter, ClassDescriptor, ValueParameterDescriptor> PARAMETER_NAME_CHANGED_ON_OVERRIDE = DiagnosticFactory2.create(WARNING, PositioningStrategies.POSITION_NAME_IDENTIFIER);
|
||||||
|
DiagnosticFactory2<JetClassOrObject, Collection<? extends CallableMemberDescriptor>, Integer> DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES = DiagnosticFactory2.create(WARNING, PositioningStrategies.POSITION_NAME_IDENTIFIER);
|
||||||
|
|
||||||
DiagnosticFactory2<JetDeclaration, CallableMemberDescriptor, String> CONFLICTING_OVERLOADS =
|
DiagnosticFactory2<JetDeclaration, CallableMemberDescriptor, String> CONFLICTING_OVERLOADS =
|
||||||
DiagnosticFactory2.create(ERROR, new PositioningStrategy<JetDeclaration>() {
|
DiagnosticFactory2.create(ERROR, new PositioningStrategy<JetDeclaration>() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -397,7 +402,7 @@ public interface Errors {
|
|||||||
JetClass klass = (JetClass)jetDeclaration;
|
JetClass klass = (JetClass)jetDeclaration;
|
||||||
PsiElement nameAsDeclaration = klass.getNameIdentifier();
|
PsiElement nameAsDeclaration = klass.getNameIdentifier();
|
||||||
if (nameAsDeclaration == null) {
|
if (nameAsDeclaration == null) {
|
||||||
return markRange(klass.getTextRange());
|
return markElement(klass);
|
||||||
}
|
}
|
||||||
PsiElement primaryConstructorParameterList = klass.getPrimaryConstructorParameterList();
|
PsiElement primaryConstructorParameterList = klass.getPrimaryConstructorParameterList();
|
||||||
if (primaryConstructorParameterList == null) {
|
if (primaryConstructorParameterList == null) {
|
||||||
@@ -410,7 +415,7 @@ public interface Errors {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// safe way
|
// safe way
|
||||||
return markRange(jetDeclaration.getTextRange());
|
return markElement(jetDeclaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -443,7 +448,7 @@ public interface Errors {
|
|||||||
class Initializer {
|
class Initializer {
|
||||||
static {
|
static {
|
||||||
for (Field field : Errors.class.getFields()) {
|
for (Field field : Errors.class.getFields()) {
|
||||||
if ((field.getModifiers() & Modifier.STATIC) != 0) {
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
try {
|
try {
|
||||||
Object value = field.get(null);
|
Object value = field.get(null);
|
||||||
if (value instanceof AbstractDiagnosticFactory) {
|
if (value instanceof AbstractDiagnosticFactory) {
|
||||||
|
|||||||
+28
-11
@@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -60,10 +59,9 @@ public class PositioningStrategies {
|
|||||||
returnTypeRef = accessor.getReturnTypeReference();
|
returnTypeRef = accessor.getReturnTypeReference();
|
||||||
nameNode = accessor.getNamePlaceholder().getNode();
|
nameNode = accessor.getNamePlaceholder().getNode();
|
||||||
}
|
}
|
||||||
if (returnTypeRef != null) return Collections.singletonList(returnTypeRef.getTextRange());
|
if (returnTypeRef != null) return markElement(returnTypeRef);
|
||||||
if (nameNode != null) return Collections.singletonList(nameNode.getTextRange());
|
if (nameNode != null) return markNode(nameNode);
|
||||||
return super.mark(declaration);
|
return markElement(declaration);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ASTNode getNameNode(JetNamedDeclaration function) {
|
private ASTNode getNameNode(JetNamedDeclaration function) {
|
||||||
@@ -76,14 +74,11 @@ public class PositioningStrategies {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<TextRange> mark(@NotNull PsiNameIdentifierOwner element) {
|
public List<TextRange> mark(@NotNull PsiNameIdentifierOwner element) {
|
||||||
if (element.getLastChild() instanceof PsiErrorElement) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
PsiElement nameIdentifier = element.getNameIdentifier();
|
PsiElement nameIdentifier = element.getNameIdentifier();
|
||||||
if (nameIdentifier != null) {
|
if (nameIdentifier != null) {
|
||||||
return markElement(nameIdentifier);
|
return markElement(nameIdentifier);
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return markElement(element);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,9 +96,9 @@ public class PositioningStrategies {
|
|||||||
assert modifierList != null;
|
assert modifierList != null;
|
||||||
ASTNode node = modifierList.getModifierNode(token);
|
ASTNode node = modifierList.getModifierNode(token);
|
||||||
assert node != null;
|
assert node != null;
|
||||||
return Collections.singletonList(node.getTextRange());
|
return markNode(node);
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return markElement(modifierListOwner);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -144,4 +139,26 @@ public class PositioningStrategies {
|
|||||||
return markNode(element.getProjectionNode());
|
return markNode(element.getProjectionNode());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static PositioningStrategy<JetParameter> PARAMETER_DEFAULT_VALUE = new PositioningStrategy<JetParameter>() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<TextRange> mark(@NotNull JetParameter element) {
|
||||||
|
return markNode(element.getDefaultValue().getNode());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static PositioningStrategy<PsiElement> CALL_ELEMENT = new PositioningStrategy<PsiElement>() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<TextRange> mark(@NotNull PsiElement callElement) {
|
||||||
|
if (callElement instanceof JetCallElement) {
|
||||||
|
JetExpression calleeExpression = ((JetCallElement) callElement).getCalleeExpression();
|
||||||
|
if (calleeExpression != null) {
|
||||||
|
return markElement(calleeExpression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return markElement(callElement);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
+4
-1
@@ -34,7 +34,10 @@ public class UnresolvedReferenceDiagnosticFactory extends DiagnosticFactory1<Jet
|
|||||||
@Override
|
@Override
|
||||||
public List<TextRange> mark(@NotNull JetReferenceExpression element) {
|
public List<TextRange> mark(@NotNull JetReferenceExpression element) {
|
||||||
if (element instanceof JetArrayAccessExpression) {
|
if (element instanceof JetArrayAccessExpression) {
|
||||||
return ((JetArrayAccessExpression) element).getBracketRanges();
|
List<TextRange> ranges = ((JetArrayAccessExpression) element).getBracketRanges();
|
||||||
|
if (!ranges.isEmpty()) {
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Collections.singletonList(element.getTextRange());
|
return Collections.singletonList(element.getTextRange());
|
||||||
}
|
}
|
||||||
|
|||||||
+35
@@ -17,7 +17,9 @@
|
|||||||
package org.jetbrains.jet.lang.diagnostics.rendering;
|
package org.jetbrains.jet.lang.diagnostics.rendering;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeConstraint;
|
import org.jetbrains.jet.lang.psi.JetTypeConstraint;
|
||||||
@@ -25,6 +27,8 @@ import org.jetbrains.jet.lang.types.JetType;
|
|||||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
@@ -385,7 +389,38 @@ public class DefaultErrorMessages {
|
|||||||
|
|
||||||
MAP.put(NOT_AN_ANNOTATION_CLASS, "''{0}'' is not an annotation class", TO_STRING);
|
MAP.put(NOT_AN_ANNOTATION_CLASS, "''{0}'' is not an annotation class", TO_STRING);
|
||||||
|
|
||||||
|
MAP.put(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE, "An overriding function is not allowed to specify default values for its parameters");
|
||||||
|
|
||||||
|
|
||||||
|
String multipleDefaultsMessage = "More than one overridden descriptor declares a default value for ''{0}''. " +
|
||||||
|
"As the compiler can not make sure these values agree, this is not allowed.";
|
||||||
|
MAP.put(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES, multipleDefaultsMessage, TO_STRING);
|
||||||
|
MAP.put(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE, multipleDefaultsMessage, TO_STRING);
|
||||||
|
|
||||||
|
MAP.put(PARAMETER_NAME_CHANGED_ON_OVERRIDE, "The corresponding parameter in the supertype ''{0}'' is named ''{1}''. " +
|
||||||
|
"This may cause problems when calling this function with named arguments.", NAME, NAME);
|
||||||
|
|
||||||
|
MAP.put(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES,
|
||||||
|
"Names of the parameter #{1} conflict in the following members of supertypes: ''{0}''" +
|
||||||
|
"This may cause problems when calling this function with named arguments.", commaSeparated(TO_STRING), TO_STRING);
|
||||||
|
|
||||||
MAP.setImmutable();
|
MAP.setImmutable();
|
||||||
|
|
||||||
|
for (Field field : Errors.class.getFields()) {
|
||||||
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
|
try {
|
||||||
|
Object fieldValue = field.get(null);
|
||||||
|
if (fieldValue instanceof AbstractDiagnosticFactory) {
|
||||||
|
if (MAP.get((AbstractDiagnosticFactory) fieldValue) == null) {
|
||||||
|
throw new IllegalStateException("No default diagnostic renderer is provided for " + ((AbstractDiagnosticFactory)fieldValue).getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultErrorMessages() {
|
private DefaultErrorMessages() {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.types.JetType;
|
|||||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
@@ -98,6 +99,24 @@ public class Renderers {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static <T> Renderer<Collection<? extends T>> commaSeparated(final Renderer<T> itemRenderer) {
|
||||||
|
return new Renderer<Collection<? extends T>>() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String render(@NotNull Collection<? extends T> object) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (Iterator<? extends T> iterator = object.iterator(); iterator.hasNext(); ) {
|
||||||
|
T next = iterator.next();
|
||||||
|
result.append(itemRenderer.render(next));
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
result.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private Renderers() {
|
private Renderers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ public interface Call {
|
|||||||
@NotNull
|
@NotNull
|
||||||
ReceiverDescriptor getExplicitReceiver();
|
ReceiverDescriptor getExplicitReceiver();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
ReceiverDescriptor getThisObject();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
JetExpression getCalleeExpression();
|
JetExpression getCalleeExpression();
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.jet.lang.psi;
|
package org.jetbrains.jet.lang.psi;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public interface JetClassOrObject extends PsiElement {
|
public interface JetClassOrObject extends PsiElement, PsiNameIdentifierOwner {
|
||||||
List<JetDeclaration> getDeclarations();
|
List<JetDeclaration> getDeclarations();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.psi;
|
package org.jetbrains.jet.lang.psi;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.impl.CheckUtil;
|
import com.intellij.psi.impl.CheckUtil;
|
||||||
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
|
||||||
@@ -308,4 +309,9 @@ public class JetPsiUtil {
|
|||||||
|
|
||||||
return "Unit".equals(typeReference.getText());
|
return "Unit".equals(typeReference.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isSafeCall(@NotNull Call call) {
|
||||||
|
ASTNode callOperationNode = call.getCallOperationNode();
|
||||||
|
return callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
|
||||||
|
|
||||||
/** A scope where type of expression has been resolved */
|
/** A scope where type of expression has been resolved */
|
||||||
|
WritableSlice<JetTypeReference, JetScope> TYPE_RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
||||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
||||||
|
|
||||||
/** Collected during analyze, used in IDE in auto-cast completion */
|
/** Collected during analyze, used in IDE in auto-cast completion */
|
||||||
@@ -75,7 +76,7 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice();
|
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice();
|
||||||
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice();
|
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice();
|
||||||
|
|
||||||
WritableSlice<VariableDescriptor, Boolean> MUST_BE_WRAPPED_IN_A_REF = Slices.createSimpleSetSlice();
|
WritableSlice<VariableDescriptor, Boolean> CAPTURED_IN_CLOSURE = Slices.createSimpleSetSlice();
|
||||||
|
|
||||||
// enum DeferredTypeKey {DEFERRED_TYPE_KEY}
|
// enum DeferredTypeKey {DEFERRED_TYPE_KEY}
|
||||||
// WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice();
|
// WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice();
|
||||||
|
|||||||
@@ -20,14 +20,10 @@ import com.google.common.collect.Lists;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableAsFunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.VariableAsFunctionResolvedCall;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
|
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
|
||||||
import org.jetbrains.jet.util.slicedmap.Slices;
|
import org.jetbrains.jet.util.slicedmap.Slices;
|
||||||
@@ -53,12 +49,12 @@ public class BindingContextUtils {
|
|||||||
throw new IllegalStateException("non-declaration descriptors should be filtered out earler: " + callable);
|
throw new IllegalStateException("non-declaration descriptors should be filtered out earler: " + callable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (declarationDescriptor instanceof VariableAsFunctionDescriptor) {
|
//if (declarationDescriptor instanceof VariableAsFunctionDescriptor) {
|
||||||
VariableAsFunctionDescriptor descriptor = (VariableAsFunctionDescriptor) declarationDescriptor;
|
// VariableAsFunctionDescriptor descriptor = (VariableAsFunctionDescriptor) declarationDescriptor;
|
||||||
if (descriptor.getOriginal() != descriptor) {
|
// if (descriptor.getOriginal() != descriptor) {
|
||||||
throw new IllegalStateException("original should be resolved earlier: " + descriptor);
|
// throw new IllegalStateException("original should be resolved earlier: " + descriptor);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
return declarationDescriptor.getOriginal();
|
return declarationDescriptor.getOriginal();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -68,7 +64,7 @@ public class BindingContextUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static PsiElement resolveToDeclarationPsiElement(@NotNull BindingContext bindingContext, @Nullable JetReferenceExpression referenceExpression) {
|
public static PsiElement resolveToDeclarationPsiElement(@NotNull BindingContext bindingContext, @Nullable JetReferenceExpression referenceExpression) {
|
||||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, referenceExpression);
|
DeclarationDescriptor declarationDescriptor = referenceToDescriptor(bindingContext, referenceExpression);
|
||||||
if (declarationDescriptor == null) {
|
if (declarationDescriptor == null) {
|
||||||
return bindingContext.get(BindingContext.LABEL_TARGET, referenceExpression);
|
return bindingContext.get(BindingContext.LABEL_TARGET, referenceExpression);
|
||||||
}
|
}
|
||||||
@@ -88,7 +84,7 @@ public class BindingContextUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<PsiElement> resolveToDeclarationPsiElements(@NotNull BindingContext bindingContext, @Nullable JetReferenceExpression referenceExpression) {
|
public static List<PsiElement> resolveToDeclarationPsiElements(@NotNull BindingContext bindingContext, @Nullable JetReferenceExpression referenceExpression) {
|
||||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, referenceExpression);
|
DeclarationDescriptor declarationDescriptor = referenceToDescriptor(bindingContext, referenceExpression);
|
||||||
if (declarationDescriptor == null) {
|
if (declarationDescriptor == null) {
|
||||||
return Lists.newArrayList(bindingContext.get(BindingContext.LABEL_TARGET, referenceExpression));
|
return Lists.newArrayList(bindingContext.get(BindingContext.LABEL_TARGET, referenceExpression));
|
||||||
}
|
}
|
||||||
@@ -114,7 +110,7 @@ public class BindingContextUtils {
|
|||||||
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||||
}
|
}
|
||||||
else if (element instanceof JetSimpleNameExpression) {
|
else if (element instanceof JetSimpleNameExpression) {
|
||||||
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
descriptor = referenceToDescriptor(bindingContext, (JetSimpleNameExpression) element);
|
||||||
}
|
}
|
||||||
else if (element instanceof JetQualifiedExpression) {
|
else if (element instanceof JetQualifiedExpression) {
|
||||||
descriptor = extractVariableDescriptorIfAny(bindingContext, ((JetQualifiedExpression) element).getSelectorExpression(), onlyReference);
|
descriptor = extractVariableDescriptorIfAny(bindingContext, ((JetQualifiedExpression) element).getSelectorExpression(), onlyReference);
|
||||||
@@ -122,12 +118,19 @@ public class BindingContextUtils {
|
|||||||
if (descriptor instanceof VariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
return (VariableDescriptor) descriptor;
|
return (VariableDescriptor) descriptor;
|
||||||
}
|
}
|
||||||
if (descriptor instanceof VariableAsFunctionDescriptor) {
|
|
||||||
return ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static DeclarationDescriptor referenceToDescriptor(@NotNull BindingContext bindingContext, @Nullable JetReferenceExpression element) {
|
||||||
|
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, element);
|
||||||
|
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, element);
|
||||||
|
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||||
|
descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getResultingDescriptor();
|
||||||
|
}
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO these helper methods are added as a workaround to some compiler bugs in Kotlin...
|
// TODO these helper methods are added as a workaround to some compiler bugs in Kotlin...
|
||||||
|
|
||||||
// NOTE this is used by KDoc
|
// NOTE this is used by KDoc
|
||||||
@@ -178,7 +181,7 @@ public class BindingContextUtils {
|
|||||||
// TODO evil code
|
// TODO evil code
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"cannot find declaration: fake descriptor" +
|
"cannot find declaration: fake descriptor" +
|
||||||
" has more then one overriden descriptor: " + callable);
|
" has more then one overridden descriptor: " + callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return callableDescriptorToDeclaration(context, overriddenDescriptors.iterator().next());
|
return callableDescriptorToDeclaration(context, overriddenDescriptors.iterator().next());
|
||||||
@@ -190,9 +193,9 @@ public class BindingContextUtils {
|
|||||||
private static List<PsiElement> callableDescriptorToDeclarations(@NotNull BindingContext context, @NotNull CallableMemberDescriptor callable) {
|
private static List<PsiElement> callableDescriptorToDeclarations(@NotNull BindingContext context, @NotNull CallableMemberDescriptor callable) {
|
||||||
if (callable.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
|
if (callable.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
|
||||||
List<PsiElement> r = new ArrayList<PsiElement>();
|
List<PsiElement> r = new ArrayList<PsiElement>();
|
||||||
Set<? extends CallableMemberDescriptor> overridenDescriptors = callable.getOverriddenDescriptors();
|
Set<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
|
||||||
for (CallableMemberDescriptor overriden : overridenDescriptors) {
|
for (CallableMemberDescriptor overridden : overriddenDescriptors) {
|
||||||
r.addAll(callableDescriptorToDeclarations(context, overriden));
|
r.addAll(callableDescriptorToDeclarations(context, overridden));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author svtk
|
||||||
|
*/
|
||||||
|
public class ChainedTemporaryBindingTrace extends TemporaryBindingTrace {
|
||||||
|
|
||||||
|
public static ChainedTemporaryBindingTrace create(TemporaryBindingTrace trace) {
|
||||||
|
return new ChainedTemporaryBindingTrace(trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChainedTemporaryBindingTrace(TemporaryBindingTrace trace) {
|
||||||
|
super(trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commit() {
|
||||||
|
super.commit();
|
||||||
|
((TemporaryBindingTrace) trace).commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,10 +21,8 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.openapi.util.Pair;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -34,6 +32,7 @@ import org.jetbrains.jet.lexer.JetKeywordToken;
|
|||||||
import org.jetbrains.jet.lexer.JetToken;
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -132,8 +131,7 @@ public class DeclarationsChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkOpenMembers(MutableClassDescriptor classDescriptor) {
|
private void checkOpenMembers(MutableClassDescriptor classDescriptor) {
|
||||||
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getCallableMembers()) {
|
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) {
|
||||||
|
|
||||||
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), memberDescriptor);
|
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), memberDescriptor);
|
||||||
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
|
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
|
||||||
trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member));
|
trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member));
|
||||||
|
|||||||
@@ -332,16 +332,33 @@ public class DescriptorResolver {
|
|||||||
return typeParameterDescriptor;
|
return typeParameterDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class UpperBoundCheckerTask {
|
||||||
|
JetTypeReference upperBound;
|
||||||
|
JetType upperBoundType;
|
||||||
|
boolean isClassObjectConstraint;
|
||||||
|
|
||||||
|
private UpperBoundCheckerTask(JetTypeReference upperBound, JetType upperBoundType, boolean classObjectConstraint) {
|
||||||
|
this.upperBound = upperBound;
|
||||||
|
this.upperBoundType = upperBoundType;
|
||||||
|
isClassObjectConstraint = classObjectConstraint;
|
||||||
|
}
|
||||||
|
}
|
||||||
public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List<TypeParameterDescriptor> parameters, BindingTrace trace) {
|
public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List<TypeParameterDescriptor> parameters, BindingTrace trace) {
|
||||||
|
List<UpperBoundCheckerTask> deferredUpperBoundCheckerTasks = Lists.newArrayList();
|
||||||
|
|
||||||
List<JetTypeParameter> typeParameters = declaration.getTypeParameters();
|
List<JetTypeParameter> typeParameters = declaration.getTypeParameters();
|
||||||
Map<String, TypeParameterDescriptor> parameterByName = Maps.newHashMap();
|
Map<String, TypeParameterDescriptor> parameterByName = Maps.newHashMap();
|
||||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
for (int i = 0; i < typeParameters.size(); i++) {
|
||||||
JetTypeParameter jetTypeParameter = typeParameters.get(i);
|
JetTypeParameter jetTypeParameter = typeParameters.get(i);
|
||||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||||
|
|
||||||
parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor);
|
parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor);
|
||||||
|
|
||||||
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
||||||
if (extendsBound != null) {
|
if (extendsBound != null) {
|
||||||
typeParameterDescriptor.addUpperBound(resolveAndCheckUpperBoundType(extendsBound, scope, false, trace));
|
JetType type = typeResolver.resolveType(scope, extendsBound, trace, false);
|
||||||
|
typeParameterDescriptor.addUpperBound(type);
|
||||||
|
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(extendsBound, type, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (JetTypeConstraint constraint : declaration.getTypeConstaints()) {
|
for (JetTypeConstraint constraint : declaration.getTypeConstaints()) {
|
||||||
@@ -355,7 +372,12 @@ public class DescriptorResolver {
|
|||||||
}
|
}
|
||||||
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName);
|
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName);
|
||||||
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
|
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
|
||||||
JetType bound = boundTypeReference != null ? resolveAndCheckUpperBoundType(boundTypeReference, scope, constraint.isClassObjectContraint(), trace) : null;
|
JetType bound = null;
|
||||||
|
if (boundTypeReference != null) {
|
||||||
|
bound = typeResolver.resolveType(scope, boundTypeReference, trace, false);
|
||||||
|
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(boundTypeReference, bound, constraint.isClassObjectContraint()));
|
||||||
|
}
|
||||||
|
|
||||||
if (typeParameterDescriptor == null) {
|
if (typeParameterDescriptor == null) {
|
||||||
// To tell the user that we look only for locally defined type parameters
|
// To tell the user that we look only for locally defined type parameters
|
||||||
ClassifierDescriptor classifier = scope.getClassifier(referencedName);
|
ClassifierDescriptor classifier = scope.getClassifier(referencedName);
|
||||||
@@ -400,19 +422,21 @@ public class DescriptorResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (UpperBoundCheckerTask checkerTask : deferredUpperBoundCheckerTasks) {
|
||||||
|
checkUpperBoundType(checkerTask.upperBound, checkerTask.upperBoundType, checkerTask.isClassObjectConstraint, trace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetType resolveAndCheckUpperBoundType(@NotNull JetTypeReference upperBound, @NotNull JetScope scope, boolean classObjectConstaint, BindingTrace trace) {
|
private static void checkUpperBoundType(JetTypeReference upperBound, JetType upperBoundType, boolean isClassObjectConstraint, BindingTrace trace) {
|
||||||
JetType jetType = typeResolver.resolveType(scope, upperBound, trace, false);
|
if (!TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, upperBoundType)) {
|
||||||
if (!TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, jetType)) {
|
if (isClassObjectConstraint) {
|
||||||
if (classObjectConstaint) {
|
trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, upperBoundType));
|
||||||
trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, jetType));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.report(FINAL_UPPER_BOUND.on(upperBound, jetType));
|
trace.report(FINAL_UPPER_BOUND.on(upperBound, upperBoundType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return jetType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public final class ImportPath {
|
|||||||
return fqName.getFqName() + (isAllUnder ? ".*" : "");
|
return fqName.getFqName() + (isAllUnder ? ".*" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getPathStr();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public FqName fqnPart() {
|
public FqName fqnPart() {
|
||||||
return fqName;
|
return fqName;
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public class OverloadResolver {
|
|||||||
) {
|
) {
|
||||||
MultiMap<String, CallableMemberDescriptor> functionsByName = MultiMap.create();
|
MultiMap<String, CallableMemberDescriptor> functionsByName = MultiMap.create();
|
||||||
|
|
||||||
for (CallableMemberDescriptor function : classDescriptor.getCallableMembers()) {
|
for (CallableMemberDescriptor function : classDescriptor.getDeclaredCallableMembers()) {
|
||||||
functionsByName.putValue(function.getName(), function);
|
functionsByName.putValue(function.getName(), function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.LinkedHashMultimap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.util.containers.LinkedMultiMap;
|
import com.intellij.util.containers.LinkedMultiMap;
|
||||||
@@ -36,7 +39,6 @@ import javax.inject.Inject;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,6 +83,7 @@ public class OverrideResolver {
|
|||||||
|
|
||||||
checkVisibility();
|
checkVisibility();
|
||||||
checkOverrides(invisibleOverriddenDescriptors);
|
checkOverrides(invisibleOverriddenDescriptors);
|
||||||
|
checkParameterOverridesForAllClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,7 +123,7 @@ public class OverrideResolver {
|
|||||||
|
|
||||||
MultiMap<String, CallableMemberDescriptor> functionsFromSupertypesByName = groupDescriptorsByName(functionsFromSupertypes);
|
MultiMap<String, CallableMemberDescriptor> functionsFromSupertypesByName = groupDescriptorsByName(functionsFromSupertypes);
|
||||||
|
|
||||||
MultiMap<String, CallableMemberDescriptor> functionsFromCurrentByName = groupDescriptorsByName(classDescriptor.getCallableMembers());
|
MultiMap<String, CallableMemberDescriptor> functionsFromCurrentByName = groupDescriptorsByName(classDescriptor.getDeclaredCallableMembers());
|
||||||
|
|
||||||
Set<String> functionNames = new LinkedHashSet<String>();
|
Set<String> functionNames = new LinkedHashSet<String>();
|
||||||
functionNames.addAll(functionsFromSupertypesByName.keySet());
|
functionNames.addAll(functionsFromSupertypesByName.keySet());
|
||||||
@@ -135,10 +138,10 @@ public class OverrideResolver {
|
|||||||
@Override
|
@Override
|
||||||
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
|
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
|
||||||
if (fakeOverride instanceof PropertyDescriptor) {
|
if (fakeOverride instanceof PropertyDescriptor) {
|
||||||
classDescriptor.getScopeForMemberLookupAsWritableScope().addPropertyDescriptor((PropertyDescriptor) fakeOverride);
|
classDescriptor.addPropertyDescriptor((PropertyDescriptor) fakeOverride);
|
||||||
}
|
}
|
||||||
else if (fakeOverride instanceof SimpleFunctionDescriptor) {
|
else if (fakeOverride instanceof SimpleFunctionDescriptor) {
|
||||||
classDescriptor.getScopeForMemberLookupAsWritableScope().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
|
classDescriptor.addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException(fakeOverride.getClass().getName());
|
throw new IllegalStateException(fakeOverride.getClass().getName());
|
||||||
@@ -176,7 +179,7 @@ public class OverrideResolver {
|
|||||||
for (CallableMemberDescriptor functionFromCurrent : functionsFromCurrent) {
|
for (CallableMemberDescriptor functionFromCurrent : functionsFromCurrent) {
|
||||||
OverridingUtil.OverrideCompatibilityInfo.Result result = OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).getResult();
|
OverridingUtil.OverrideCompatibilityInfo.Result result = OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).getResult();
|
||||||
if (result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) {
|
if (result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) {
|
||||||
functionFromCurrent.addOverriddenDescriptor(functionFromSupertype);
|
OverridingUtil.bindOverride(functionFromCurrent, functionFromSupertype);
|
||||||
overrides = true;
|
overrides = true;
|
||||||
}
|
}
|
||||||
else if (result == OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT) {
|
else if (result == OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT) {
|
||||||
@@ -186,14 +189,14 @@ public class OverrideResolver {
|
|||||||
|
|
||||||
for (CallableMemberDescriptor fakeOverride : fakeOverrideList) {
|
for (CallableMemberDescriptor fakeOverride : fakeOverrideList) {
|
||||||
if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) {
|
if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) {
|
||||||
fakeOverride.addOverriddenDescriptor(functionFromSupertype);
|
OverridingUtil.bindOverride(fakeOverride, functionFromSupertype);
|
||||||
overrides = true;
|
overrides = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overrides) {
|
if (!overrides) {
|
||||||
CallableMemberDescriptor fakeOverride = functionFromSupertype.copy(current, false, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
|
CallableMemberDescriptor fakeOverride = functionFromSupertype.copy(current, false, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
|
||||||
fakeOverride.addOverriddenDescriptor(functionFromSupertype);
|
OverridingUtil.bindOverride(fakeOverride, functionFromSupertype);
|
||||||
fakeOverrideList.add(fakeOverride);
|
fakeOverrideList.add(fakeOverride);
|
||||||
if (fakeOverrides != null) {
|
if (fakeOverrides != null) {
|
||||||
fakeOverrides.add(fakeOverride);
|
fakeOverrides.add(fakeOverride);
|
||||||
@@ -203,7 +206,6 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static <T extends DeclarationDescriptor> MultiMap<String, T> groupDescriptorsByName(Collection<T> properties) {
|
private static <T extends DeclarationDescriptor> MultiMap<String, T> groupDescriptorsByName(Collection<T> properties) {
|
||||||
MultiMap<String, T> r = new LinkedMultiMap<String, T>();
|
MultiMap<String, T> r = new LinkedMultiMap<String, T>();
|
||||||
for (T property : properties) {
|
for (T property : properties) {
|
||||||
@@ -246,7 +248,7 @@ public class OverrideResolver {
|
|||||||
if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return;
|
if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return;
|
||||||
|
|
||||||
// Check overrides for internal consistency
|
// Check overrides for internal consistency
|
||||||
for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) {
|
for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
|
||||||
checkOverrideForMember(member, invisibleOverriddenDescriptors);
|
checkOverrideForMember(member, invisibleOverriddenDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,10 +260,10 @@ public class OverrideResolver {
|
|||||||
|
|
||||||
PsiElement nameIdentifier = null;
|
PsiElement nameIdentifier = null;
|
||||||
if (klass instanceof JetClass) {
|
if (klass instanceof JetClass) {
|
||||||
nameIdentifier = ((JetClass) klass).getNameIdentifier();
|
nameIdentifier = klass.getNameIdentifier();
|
||||||
}
|
}
|
||||||
else if (klass instanceof JetObjectDeclaration) {
|
else if (klass instanceof JetObjectDeclaration) {
|
||||||
nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier();
|
nameIdentifier = klass.getNameIdentifier();
|
||||||
if (nameIdentifier == null) {
|
if (nameIdentifier == null) {
|
||||||
nameIdentifier = ((JetObjectDeclaration) klass).getObjectKeyword();
|
nameIdentifier = ((JetObjectDeclaration) klass).getObjectKeyword();
|
||||||
}
|
}
|
||||||
@@ -285,24 +287,16 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
||||||
|
for (CallableMemberDescriptor descriptor : classDescriptor.getAllCallableMembers()) {
|
||||||
for (DeclarationDescriptor descriptor : classDescriptor.getScopeForMemberLookup().getAllDescriptors()) {
|
collectMissingImplementations(descriptor, abstractNoImpl, manyImpl);
|
||||||
if (descriptor instanceof CallableMemberDescriptor) {
|
|
||||||
collectMissingImplementations((CallableMemberDescriptor) descriptor, abstractNoImpl, manyImpl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void collectMissingImplementations(CallableMemberDescriptor descriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
private static void collectMissingImplementations(CallableMemberDescriptor descriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
|
||||||
if (descriptor.getKind().isReal()) {
|
if (!descriptor.getKind().isReal()) {
|
||||||
if (descriptor.getModality() == Modality.ABSTRACT) {
|
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
|
||||||
//abstractNoImpl.add(descriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverridenDeclarations(descriptor);
|
|
||||||
if (overriddenDeclarations.size() == 0) {
|
if (overriddenDeclarations.size() == 0) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException("A 'fake override' must override something");
|
||||||
}
|
}
|
||||||
else if (overriddenDeclarations.size() == 1) {
|
else if (overriddenDeclarations.size() == 1) {
|
||||||
CallableMemberDescriptor single = overriddenDeclarations.iterator().next();
|
CallableMemberDescriptor single = overriddenDeclarations.iterator().next();
|
||||||
@@ -312,7 +306,8 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
List<CallableMemberDescriptor> nonAbstractManyImpl = Lists.newArrayList();
|
List<CallableMemberDescriptor> nonAbstractManyImpl = Lists.newArrayList();
|
||||||
for (CallableMemberDescriptor overridden : overriddenDeclarations) {
|
Set<CallableMemberDescriptor> filteredOverriddenDeclarations = OverridingUtil.filterOverrides(Sets.newHashSet(overriddenDeclarations));
|
||||||
|
for (CallableMemberDescriptor overridden : filteredOverriddenDeclarations) {
|
||||||
if (overridden.getModality() != Modality.ABSTRACT) {
|
if (overridden.getModality() != Modality.ABSTRACT) {
|
||||||
nonAbstractManyImpl.add(overridden);
|
nonAbstractManyImpl.add(overridden);
|
||||||
}
|
}
|
||||||
@@ -393,6 +388,7 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
|
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
|
||||||
if (!invisibleOverriddenDescriptors.get(declared).isEmpty()) {
|
if (!invisibleOverriddenDescriptors.get(declared).isEmpty()) {
|
||||||
CallableDescriptor descriptor = invisibleOverriddenDescriptors.values().iterator().next();
|
CallableDescriptor descriptor = invisibleOverriddenDescriptors.values().iterator().next();
|
||||||
@@ -409,6 +405,74 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkParameterOverridesForAllClasses() {
|
||||||
|
List<MutableClassDescriptor> allClasses = Lists.newArrayList(context.getClasses().values());
|
||||||
|
allClasses.addAll(context.getObjects().values());
|
||||||
|
for (MutableClassDescriptor classDescriptor : allClasses) {
|
||||||
|
Collection<CallableMemberDescriptor> members = classDescriptor.getAllCallableMembers();
|
||||||
|
for (CallableMemberDescriptor member : members) {
|
||||||
|
checkOverridesForParameters(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkOverridesForParameters(CallableMemberDescriptor declared) {
|
||||||
|
boolean fakeOverride = declared.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
|
||||||
|
if (!fakeOverride) {
|
||||||
|
// No check if the function is not marked as 'override'
|
||||||
|
JetModifierListOwner declaration =
|
||||||
|
(JetModifierListOwner) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
|
||||||
|
if (!declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let p1 be a parameter of the overriding function
|
||||||
|
// Let p2 be a parameter of the function being overridden
|
||||||
|
// Then
|
||||||
|
// a) p1 is not allowed to have a default value declared
|
||||||
|
// b) p1 must have the same name as p2
|
||||||
|
for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
|
||||||
|
JetParameter parameter =
|
||||||
|
fakeOverride ? null :
|
||||||
|
(JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
|
||||||
|
|
||||||
|
JetClassOrObject classElement = fakeOverride ? (JetClassOrObject) BindingContextUtils
|
||||||
|
.descriptorToDeclaration(trace.getBindingContext(), declared.getContainingDeclaration()) : null;
|
||||||
|
|
||||||
|
if (parameterFromSubclass.declaresDefaultValue() && !fakeOverride) {
|
||||||
|
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean superWithDefault = false;
|
||||||
|
for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
|
||||||
|
if (parameterFromSuperclass.declaresDefaultValue()) {
|
||||||
|
if (!superWithDefault) {
|
||||||
|
superWithDefault = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fakeOverride) {
|
||||||
|
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, parameterFromSubclass));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, parameterFromSubclass));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parameterFromSuperclass.getName().equals(parameterFromSubclass.getName())) {
|
||||||
|
if (fakeOverride) {
|
||||||
|
trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(classElement, declared.getOverriddenDescriptors(), parameterFromSuperclass.getIndex() + 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(parameter, (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(), parameterFromSuperclass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) {
|
private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) {
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
|
|||||||
@@ -244,17 +244,17 @@ public class OverridingUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get overriden descriptors that are declarations or delegations.
|
* Get overridden descriptors that are declarations or delegations.
|
||||||
*
|
*
|
||||||
* @see CallableMemberDescriptor.Kind#isReal()
|
* @see CallableMemberDescriptor.Kind#isReal()
|
||||||
*/
|
*/
|
||||||
public static Collection<CallableMemberDescriptor> getOverridenDeclarations(CallableMemberDescriptor descriptor) {
|
public static Collection<CallableMemberDescriptor> getOverriddenDeclarations(CallableMemberDescriptor descriptor) {
|
||||||
Map<ClassDescriptor, CallableMemberDescriptor> result = Maps.newHashMap();
|
Map<ClassDescriptor, CallableMemberDescriptor> result = Maps.newHashMap();
|
||||||
getOverridenDeclarations(descriptor, result);
|
getOverriddenDeclarations(descriptor, result);
|
||||||
return result.values();
|
return result.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void getOverridenDeclarations(CallableMemberDescriptor descriptor, Map<ClassDescriptor, CallableMemberDescriptor> r) {
|
private static void getOverriddenDeclarations(CallableMemberDescriptor descriptor, Map<ClassDescriptor, CallableMemberDescriptor> r) {
|
||||||
if (descriptor.getKind().isReal()) {
|
if (descriptor.getKind().isReal()) {
|
||||||
r.put((ClassDescriptor) descriptor.getContainingDeclaration(), descriptor);
|
r.put((ClassDescriptor) descriptor.getContainingDeclaration(), descriptor);
|
||||||
}
|
}
|
||||||
@@ -262,12 +262,23 @@ public class OverridingUtil {
|
|||||||
if (descriptor.getOverriddenDescriptors().isEmpty()) {
|
if (descriptor.getOverriddenDescriptors().isEmpty()) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
for (CallableMemberDescriptor overriden : descriptor.getOverriddenDescriptors()) {
|
for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
|
||||||
getOverridenDeclarations(overriden, r);
|
getOverriddenDeclarations(overridden, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void bindOverride(CallableMemberDescriptor fromCurrent, CallableMemberDescriptor fromSupertype) {
|
||||||
|
fromCurrent.addOverriddenDescriptor(fromSupertype);
|
||||||
|
|
||||||
|
for (ValueParameterDescriptor parameterFromCurrent : fromCurrent.getValueParameters()) {
|
||||||
|
assert parameterFromCurrent.getIndex() < fromSupertype.getValueParameters().size()
|
||||||
|
: "An override relation between functions implies that they have the same number of value parameters";
|
||||||
|
ValueParameterDescriptor parameterFromSupertype = fromSupertype.getValueParameters().get(parameterFromCurrent.getIndex());
|
||||||
|
parameterFromCurrent.addOverriddenDescriptor(parameterFromSupertype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class OverrideCompatibilityInfo {
|
public static class OverrideCompatibilityInfo {
|
||||||
|
|
||||||
public enum Result {
|
public enum Result {
|
||||||
|
|||||||
@@ -25,10 +25,9 @@ public class TemporaryBindingTrace extends DelegatingBindingTrace {
|
|||||||
return new TemporaryBindingTrace(trace);
|
return new TemporaryBindingTrace(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BindingTrace trace;
|
protected final BindingTrace trace;
|
||||||
|
|
||||||
|
protected TemporaryBindingTrace(BindingTrace trace) {
|
||||||
private TemporaryBindingTrace(BindingTrace trace) {
|
|
||||||
super(trace.getBindingContext());
|
super(trace.getBindingContext());
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,7 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
|
||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
@@ -379,7 +376,8 @@ public class TypeHierarchyResolver {
|
|||||||
|
|
||||||
private void checkSupertypesForConsistency() {
|
private void checkSupertypesForConsistency() {
|
||||||
for (MutableClassDescriptor mutableClassDescriptor : topologicalOrder) {
|
for (MutableClassDescriptor mutableClassDescriptor : topologicalOrder) {
|
||||||
Multimap<TypeConstructor, TypeProjection> multimap = TypeUtils.buildDeepSubstitutionMultimap(mutableClassDescriptor.getDefaultType());
|
Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils
|
||||||
|
.buildDeepSubstitutionMultimap(mutableClassDescriptor.getDefaultType());
|
||||||
for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
|
for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
|
||||||
Collection<TypeProjection> projections = entry.getValue();
|
Collection<TypeProjection> projections = entry.getValue();
|
||||||
if (projections.size() > 1) {
|
if (projections.size() > 1) {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ public class TypeResolver {
|
|||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
JetType type = resolveTypeElement(scope, annotations, typeElement, false, trace, checkBounds);
|
JetType type = resolveTypeElement(scope, annotations, typeElement, false, trace, checkBounds);
|
||||||
trace.record(BindingContext.TYPE, typeReference, type);
|
trace.record(BindingContext.TYPE, typeReference, type);
|
||||||
|
trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, scope);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -243,7 +244,7 @@ public class TypeResolver {
|
|||||||
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||||
if (parameters.size() > i) {
|
if (parameters.size() > i) {
|
||||||
TypeParameterDescriptor parameterDescriptor = parameters.get(i);
|
TypeParameterDescriptor parameterDescriptor = parameters.get(i);
|
||||||
arguments.add(TypeUtils.makeStarProjection(parameterDescriptor));
|
arguments.add(SubstitutionUtils.makeStarProjection(parameterDescriptor));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
arguments.add(new TypeProjection(Variance.OUT_VARIANCE, ErrorUtils.createErrorType("*")));
|
arguments.add(new TypeProjection(Variance.OUT_VARIANCE, ErrorUtils.createErrorType("*")));
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ public class CallMaker {
|
|||||||
return explicitReceiver;
|
return explicitReceiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getThisObject() {
|
||||||
|
return ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetExpression getCalleeExpression() {
|
public JetExpression getCalleeExpression() {
|
||||||
return calleeExpression;
|
return calleeExpression;
|
||||||
@@ -199,6 +205,12 @@ public class CallMaker {
|
|||||||
return explicitReceiver;
|
return explicitReceiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getThisObject() {
|
||||||
|
return ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetExpression getCalleeExpression() {
|
public JetExpression getCalleeExpression() {
|
||||||
return callElement.getCalleeExpression();
|
return callElement.getCalleeExpression();
|
||||||
|
|||||||
+10
-4
@@ -20,21 +20,27 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
import org.jetbrains.jet.lang.psi.Call;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
public final class CallResolutionContext<D extends CallableDescriptor> extends ResolutionContext {
|
public final class CallResolutionContext<D extends CallableDescriptor, F extends D> extends ResolutionContext {
|
||||||
/*package*/ final ResolvedCallImpl<D> candidateCall;
|
/*package*/ final ResolvedCallImpl<D> candidateCall;
|
||||||
/*package*/ final TracingStrategy tracing;
|
/*package*/ final TracingStrategy tracing;
|
||||||
|
/*package*/ ReceiverDescriptor receiverForVariableAsFunctionSecondCall = ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
|
||||||
public CallResolutionContext(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing, @NotNull Call call) {
|
private CallResolutionContext(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D, F> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing, @NotNull Call call) {
|
||||||
super(trace, task.scope, call, task.expectedType, task.dataFlowInfo);
|
super(trace, task.scope, call, task.expectedType, task.dataFlowInfo);
|
||||||
this.candidateCall = candidateCall;
|
this.candidateCall = candidateCall;
|
||||||
this.tracing = tracing;
|
this.tracing = tracing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallResolutionContext(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
|
public static <D extends CallableDescriptor, F extends D> CallResolutionContext<D, F> create(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D, F> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing, @NotNull Call call) {
|
||||||
this(candidateCall, task, trace, tracing, task.call);
|
return new CallResolutionContext<D, F>(candidateCall, task, trace, tracing, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <D extends CallableDescriptor, F extends D> CallResolutionContext<D, F> create(@NotNull ResolvedCallImpl<D> candidateCall, @NotNull ResolutionTask<D, F> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
|
||||||
|
return create(candidateCall, task, trace, tracing, task.call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,16 +102,16 @@ public class CallResolver {
|
|||||||
if (referencedName == null) {
|
if (referencedName == null) {
|
||||||
return OverloadResolutionResultsImpl.nameNotFound();
|
return OverloadResolutionResultsImpl.nameNotFound();
|
||||||
}
|
}
|
||||||
List<MemberPrioritizer<VariableDescriptor>> memberPrioritizers = Lists.newArrayList();
|
List<CallableDescriptorCollector<? extends VariableDescriptor>> callableDescriptorCollectors = Lists.newArrayList();
|
||||||
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
|
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
|
||||||
referencedName = referencedName.substring(1);
|
referencedName = referencedName.substring(1);
|
||||||
memberPrioritizers.add(MemberPrioritizers.PROPERTY_TASK_PRIORITIZER);
|
callableDescriptorCollectors.add(CallableDescriptorCollectors.PROPERTIES);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memberPrioritizers.add(MemberPrioritizers.VARIABLE_TASK_PRIORITIZER);
|
callableDescriptorCollectors.add(CallableDescriptorCollectors.VARIABLES);
|
||||||
}
|
}
|
||||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, memberPrioritizers);
|
List<ResolutionTask<VariableDescriptor, VariableDescriptor>> prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, referencedName, nameExpression, callableDescriptorCollectors);
|
||||||
return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.PROPERTY_CALL_TRANSFORMATION_STRATEGY, nameExpression);
|
return doResolveCall(context, prioritizedTasks, CallTransformer.PROPERTY_CALL_TRANSFORMER, nameExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -119,9 +119,8 @@ public class CallResolver {
|
|||||||
@NotNull BasicResolutionContext context,
|
@NotNull BasicResolutionContext context,
|
||||||
@NotNull final JetReferenceExpression functionReference,
|
@NotNull final JetReferenceExpression functionReference,
|
||||||
@NotNull String name) {
|
@NotNull String name) {
|
||||||
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizer.computePrioritizedTasks(
|
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
|
||||||
context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
|
return doResolveCall(context, tasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
|
||||||
return doResolveCall(context, tasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -131,7 +130,7 @@ public class CallResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicResolutionContext context) {
|
public OverloadResolutionResults<FunctionDescriptor> resolveFunctionCall(@NotNull BasicResolutionContext context) {
|
||||||
List<ResolutionTask<FunctionDescriptor>> prioritizedTasks;
|
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
|
||||||
|
|
||||||
JetExpression calleeExpression = context.call.getCalleeExpression();
|
JetExpression calleeExpression = context.call.getCalleeExpression();
|
||||||
final JetReferenceExpression functionReference;
|
final JetReferenceExpression functionReference;
|
||||||
@@ -142,7 +141,7 @@ public class CallResolver {
|
|||||||
String name = expression.getReferencedName();
|
String name = expression.getReferencedName();
|
||||||
if (name == null) return checkArgumentTypesAndFail(context);
|
if (name == null) return checkArgumentTypesAndFail(context);
|
||||||
|
|
||||||
prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, Collections.singletonList(MemberPrioritizers.FUNCTION_TASK_PRIORITIZER));
|
prioritizedTasks = TaskPrioritizer.computePrioritizedTasks(context, name, functionReference, CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES);
|
||||||
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
|
ResolutionTask.DescriptorCheckStrategy abstractConstructorCheck = new ResolutionTask.DescriptorCheckStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
|
public <D extends CallableDescriptor> boolean performAdvancedChecks(D descriptor, BindingTrace trace, TracingStrategy tracing) {
|
||||||
@@ -184,8 +183,11 @@ public class CallResolver {
|
|||||||
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||||
return checkArgumentTypesAndFail(context);
|
return checkArgumentTypesAndFail(context);
|
||||||
}
|
}
|
||||||
Collection<ResolutionCandidate<FunctionDescriptor>> candidates = TaskPrioritizer.<FunctionDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors);
|
Collection<ResolutionCandidate<CallableDescriptor>> candidates = TaskPrioritizer.<CallableDescriptor>convertWithImpliedThis(context.scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors);
|
||||||
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
|
for (ResolutionCandidate<CallableDescriptor> candidate : candidates) {
|
||||||
|
candidate.setSafeCall(JetPsiUtil.isSafeCall(context.call));
|
||||||
|
}
|
||||||
|
prioritizedTasks.add(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context.trace.report(NOT_A_CLASS.on(calleeExpression));
|
context.trace.report(NOT_A_CLASS.on(calleeExpression));
|
||||||
@@ -206,8 +208,8 @@ public class CallResolver {
|
|||||||
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
context.trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||||
return checkArgumentTypesAndFail(context);
|
return checkArgumentTypesAndFail(context);
|
||||||
}
|
}
|
||||||
List<ResolutionCandidate<FunctionDescriptor>> candidates = ResolutionCandidate.<FunctionDescriptor>convertCollection(constructors);
|
List<ResolutionCandidate<CallableDescriptor>> candidates = ResolutionCandidate.<CallableDescriptor>convertCollection(constructors, JetPsiUtil.isSafeCall(context.call));
|
||||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
|
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(candidates, functionReference, context)); // !! DataFlowInfo.EMPTY
|
||||||
}
|
}
|
||||||
else if (calleeExpression != null) {
|
else if (calleeExpression != null) {
|
||||||
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
||||||
@@ -222,16 +224,17 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
|
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), "[for expression " + calleeExpression.getText() + "]");
|
||||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER);
|
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER, Modality.FINAL, Visibilities.LOCAL);
|
||||||
ResolutionCandidate<FunctionDescriptor> resolutionCandidate = ResolutionCandidate.<FunctionDescriptor>create(functionDescriptor);
|
ResolutionCandidate<CallableDescriptor> resolutionCandidate = ResolutionCandidate.<CallableDescriptor>create(functionDescriptor, JetPsiUtil.isSafeCall(context.call));
|
||||||
resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
|
resolutionCandidate.setReceiverArgument(context.call.getExplicitReceiver());
|
||||||
|
resolutionCandidate.setExplicitReceiverKind(ExplicitReceiverKind.RECEIVER_ARGUMENT);
|
||||||
|
|
||||||
// strictly speaking, this is a hack:
|
// strictly speaking, this is a hack:
|
||||||
// we need to pass a reference, but there's no reference in the PSI,
|
// 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)
|
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
|
||||||
functionReference = new JetFakeReference(calleeExpression);
|
functionReference = new JetFakeReference(calleeExpression);
|
||||||
|
|
||||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context));
|
prioritizedTasks = Collections.singletonList(new ResolutionTask<CallableDescriptor, FunctionDescriptor>(Collections.singleton(resolutionCandidate), functionReference, context));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// checkTypesWithNoCallee(trace, scope, call);
|
// checkTypesWithNoCallee(trace, scope, call);
|
||||||
@@ -239,7 +242,7 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return doResolveCall(context, prioritizedTasks, CallTransformationStrategy.FUNCTION_CALL_TRANSFORMATION_STRATEGY, functionReference);
|
return doResolveCall(context, prioritizedTasks, CallTransformer.FUNCTION_CALL_TRANSFORMER, functionReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
|
private <D extends CallableDescriptor> OverloadResolutionResults<D> checkArgumentTypesAndFail(BasicResolutionContext context) {
|
||||||
@@ -248,10 +251,10 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> doResolveCall(
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResults<F> doResolveCall(
|
||||||
@NotNull final BasicResolutionContext context,
|
@NotNull final BasicResolutionContext context,
|
||||||
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
|
@NotNull final List<ResolutionTask<D, F>> prioritizedTasks, // high to low priority
|
||||||
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy,
|
@NotNull CallTransformer<D, F> callTransformer,
|
||||||
@NotNull final JetReferenceExpression reference) {
|
@NotNull final JetReferenceExpression reference) {
|
||||||
|
|
||||||
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
|
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
|
||||||
@@ -265,10 +268,11 @@ public class CallResolver {
|
|||||||
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
|
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
|
||||||
|
|
||||||
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
||||||
OverloadResolutionResultsImpl<D> resultsForFirstNonemptyCandidateSet = null;
|
OverloadResolutionResultsImpl<F> resultsForFirstNonemptyCandidateSet = null;
|
||||||
for (ResolutionTask<D> task : prioritizedTasks) {
|
for (ResolutionTask<D, F> task : prioritizedTasks) {
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace);
|
||||||
OverloadResolutionResultsImpl<D> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace), callTransformationStrategy);
|
OverloadResolutionResultsImpl<F> results = performResolutionGuardedForExtraFunctionLiteralArguments(task.withTrace(temporaryTrace),
|
||||||
|
callTransformer);
|
||||||
if (results.isSuccess() || results.isAmbiguity()) {
|
if (results.isSuccess() || results.isAmbiguity()) {
|
||||||
temporaryTrace.commit();
|
temporaryTrace.commit();
|
||||||
|
|
||||||
@@ -294,15 +298,15 @@ public class CallResolver {
|
|||||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference));
|
context.trace.report(UNRESOLVED_REFERENCE.on(reference));
|
||||||
checkTypesWithNoCallee(context);
|
checkTypesWithNoCallee(context);
|
||||||
}
|
}
|
||||||
return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<D>nameNotFound();
|
return resultsForFirstNonemptyCandidateSet != null ? resultsForFirstNonemptyCandidateSet : OverloadResolutionResultsImpl.<F>nameNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask<D> task,
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolutionGuardedForExtraFunctionLiteralArguments(@NotNull ResolutionTask<D, F> task,
|
||||||
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy) {
|
@NotNull CallTransformer<D, F> callTransformer) {
|
||||||
OverloadResolutionResultsImpl<D> results = performResolution(task, callTransformationStrategy);
|
OverloadResolutionResultsImpl<F> results = performResolution(task, callTransformer);
|
||||||
|
|
||||||
// If resolution fails, we should check for some of the following situations:
|
// If resolution fails, we should check for some of the following situations:
|
||||||
// class A {
|
// class A {
|
||||||
@@ -327,16 +331,16 @@ public class CallResolver {
|
|||||||
// Now, we try to remove this argument and see if it helps
|
// Now, we try to remove this argument and see if it helps
|
||||||
Collection<ResolutionCandidate<D>> newCandidates = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> newCandidates = Lists.newArrayList();
|
||||||
for (ResolutionCandidate<D> candidate : task.getCandidates()) {
|
for (ResolutionCandidate<D> candidate : task.getCandidates()) {
|
||||||
newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor()));
|
newCandidates.add(ResolutionCandidate.create(candidate.getDescriptor(), candidate.isSafeCall())); //todo check receivers are not necessary
|
||||||
}
|
}
|
||||||
ResolutionTask<D> newContext = new ResolutionTask<D>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) {
|
ResolutionTask<D, F> newContext = new ResolutionTask<D, F>(newCandidates, task.reference, TemporaryBindingTrace.create(task.trace), task.scope, new DelegatingCall(task.call) {
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<JetExpression> getFunctionLiteralArguments() {
|
public List<JetExpression> getFunctionLiteralArguments() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}, task.expectedType, task.dataFlowInfo);
|
}, task.expectedType, task.dataFlowInfo);
|
||||||
OverloadResolutionResultsImpl<D> resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformationStrategy);
|
OverloadResolutionResultsImpl<F> resultsWithFunctionLiteralsStripped = performResolution(newContext, callTransformer);
|
||||||
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
|
if (resultsWithFunctionLiteralsStripped.isSuccess() || resultsWithFunctionLiteralsStripped.isAmbiguity()) {
|
||||||
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
|
task.tracing.danglingFunctionLiteralArgumentSuspected(task.trace, task.call.getFunctionLiteralArguments());
|
||||||
}
|
}
|
||||||
@@ -346,23 +350,28 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> performResolution(@NotNull ResolutionTask<D> task,
|
private <D extends CallableDescriptor, F extends D> OverloadResolutionResultsImpl<F> performResolution(@NotNull ResolutionTask<D, F> task,
|
||||||
@NotNull CallTransformationStrategy<D, D> callTransformationStrategy) {
|
@NotNull CallTransformer<D, F> callTransformer) {
|
||||||
|
|
||||||
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
|
for (ResolutionCandidate<D> resolutionCandidate : task.getCandidates()) {
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace);
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(task.trace);
|
||||||
CallResolutionContext<D> context = callTransformationStrategy.createCallContext(resolutionCandidate, task, temporaryTrace, task.tracing);
|
Collection<CallResolutionContext<D, F>> contexts = callTransformer.createCallContexts(resolutionCandidate, task, temporaryTrace);
|
||||||
performResolutionForCandidateCall(context, task, temporaryTrace);
|
Collection<ResolvedCallWithTrace<F>> calls = Lists.newArrayList();
|
||||||
|
for (CallResolutionContext<D, F> context : contexts) {
|
||||||
|
|
||||||
Collection<ResolvedCallImpl<D>> calls = callTransformationStrategy.transformResultCall(context, this, task);
|
performResolutionForCandidateCall(context, task);
|
||||||
for (ResolvedCallImpl<D> call : calls) {
|
calls.addAll(callTransformer.transformCall(context, this, task));
|
||||||
task.getResolvedCallMap().put(resolutionCandidate, call);
|
}
|
||||||
|
for (ResolvedCallWithTrace<F> call : calls) {
|
||||||
|
|
||||||
|
task.tracing.bindResolvedCall(call.getTrace(), call);
|
||||||
|
task.getResolvedCalls().add(call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ResolvedCallImpl<D>> successfulCandidates = Sets.newLinkedHashSet();
|
Set<ResolvedCallWithTrace<F>> successfulCandidates = Sets.newLinkedHashSet();
|
||||||
Set<ResolvedCallImpl<D>> failedCandidates = Sets.newLinkedHashSet();
|
Set<ResolvedCallWithTrace<F>> failedCandidates = Sets.newLinkedHashSet();
|
||||||
for (ResolvedCallImpl<D> candidateCall : task.getResolvedCallMap().values()) {
|
for (ResolvedCallWithTrace<F> candidateCall : task.getResolvedCalls()) {
|
||||||
ResolutionStatus status = candidateCall.getStatus();
|
ResolutionStatus status = candidateCall.getStatus();
|
||||||
if (status.isSuccess()) {
|
if (status.isSuccess()) {
|
||||||
successfulCandidates.add(candidateCall);
|
successfulCandidates.add(candidateCall);
|
||||||
@@ -373,23 +382,19 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OverloadResolutionResultsImpl<D> results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates);
|
OverloadResolutionResultsImpl<F> results = computeResultAndReportErrors(task.trace, task.tracing, successfulCandidates, failedCandidates);
|
||||||
if (!results.isSingleResult()) {
|
if (!results.isSingleResult()) {
|
||||||
checkTypesWithNoCallee(task.toBasic());
|
checkTypesWithNoCallee(task.toBasic());
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> void performResolutionForCandidateCall(@NotNull CallResolutionContext<D> context,
|
private <D extends CallableDescriptor, F extends D> void performResolutionForCandidateCall(@NotNull CallResolutionContext<D, F> context,
|
||||||
@NotNull ResolutionTask<D> task,
|
@NotNull ResolutionTask<D, F> task) {
|
||||||
@NotNull TemporaryBindingTrace temporaryTrace) {
|
|
||||||
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
||||||
|
|
||||||
candidateCall.setTrace(temporaryTrace);
|
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
context.tracing.bindReference(context.trace, candidateCall);
|
|
||||||
|
|
||||||
if (ErrorUtils.isError(candidate)) {
|
if (ErrorUtils.isError(candidate)) {
|
||||||
candidateCall.addStatus(SUCCESS);
|
candidateCall.addStatus(SUCCESS);
|
||||||
checkTypesWithNoCallee(context.toBasic());
|
checkTypesWithNoCallee(context.toBasic());
|
||||||
@@ -477,7 +482,7 @@ public class CallResolver {
|
|||||||
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
|
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> ResolutionStatus inferTypeArguments(CallResolutionContext<D> context) {
|
private <D extends CallableDescriptor, F extends D> ResolutionStatus inferTypeArguments(CallResolutionContext<D, F> context) {
|
||||||
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
ResolvedCallImpl<D> candidateCall = context.candidateCall;
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
@@ -624,23 +629,37 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> ResolutionStatus checkAllValueArguments(CallResolutionContext<D> context) {
|
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkAllValueArguments(CallResolutionContext<D, F> context) {
|
||||||
ResolutionStatus result = checkValueArgumentTypes(context);
|
ResolutionStatus result = checkValueArgumentTypes(context);
|
||||||
ResolvedCall candidateCall = context.candidateCall;
|
ResolvedCall<D> candidateCall = context.candidateCall;
|
||||||
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument()));
|
|
||||||
result = result.combine(checkReceiver(context, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject()));
|
// Comment about a very special case.
|
||||||
|
// Call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' should be checked two times for safe call (in 'checkReceiver'), because
|
||||||
|
// both 'b' (receiver) and 'foo' (this object) might be nullable. In the first case we mark dot, in the second 'foo'.
|
||||||
|
// Class 'CallForImplicitInvoke' helps up to recognise this case, and parameter 'implicitInvokeCheck' helps us to distinguish whether we check receiver or this object.
|
||||||
|
|
||||||
|
result = result.combine(checkReceiver(context, candidateCall, candidateCall.getResultingDescriptor().getReceiverParameter(), candidateCall.getReceiverArgument(),
|
||||||
|
candidateCall.getExplicitReceiverKind().isReceiver(), false));
|
||||||
|
|
||||||
|
result = result.combine(checkReceiver(context, candidateCall, candidateCall.getResultingDescriptor().getExpectedThisObject(), candidateCall.getThisObject(),
|
||||||
|
candidateCall.getExplicitReceiverKind().isThisObject(),
|
||||||
|
// for the invocation 'foo(1)' where foo is a variable of function type we should mark 'foo' if there is unsafe call error
|
||||||
|
context.call instanceof CallTransformer.CallForImplicitInvoke));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> ResolutionStatus checkReceiver(CallResolutionContext<D> context, ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument) {
|
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkReceiver(CallResolutionContext<D, F> context, ResolvedCall<D> candidateCall,
|
||||||
|
ReceiverDescriptor receiverParameter, ReceiverDescriptor receiverArgument,
|
||||||
|
boolean isExplicitReceiver, boolean implicitInvokeCheck) {
|
||||||
|
|
||||||
ResolutionStatus result = SUCCESS;
|
ResolutionStatus result = SUCCESS;
|
||||||
if (receiverParameter.exists() && receiverArgument.exists()) {
|
if (receiverParameter.exists() && receiverArgument.exists()) {
|
||||||
ASTNode callOperationNode = context.call.getCallOperationNode();
|
boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && candidateCall.isSafeCall();
|
||||||
boolean safeAccess = callOperationNode != null && callOperationNode.getElementType() == JetTokens.SAFE_ACCESS;
|
|
||||||
JetType receiverArgumentType = receiverArgument.getType();
|
JetType receiverArgumentType = receiverArgument.getType();
|
||||||
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.candidateCall.getTrace().getBindingContext());
|
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.candidateCall.getTrace().getBindingContext());
|
||||||
if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
|
if (!safeAccess && !receiverParameter.getType().isNullable() && !autoCastService.isNotNull(receiverArgument)) {
|
||||||
context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType);
|
|
||||||
|
context.tracing.unsafeCall(context.candidateCall.getTrace(), receiverArgumentType, implicitInvokeCheck);
|
||||||
result = UNSAFE_CALL_ERROR;
|
result = UNSAFE_CALL_ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -652,7 +671,6 @@ public class CallResolver {
|
|||||||
result = OTHER_ERROR;
|
result = OTHER_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) {
|
if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) {
|
||||||
context.tracing.unnecessarySafeCall(context.candidateCall.getTrace(), receiverArgumentType);
|
context.tracing.unnecessarySafeCall(context.candidateCall.getTrace(), receiverArgumentType);
|
||||||
}
|
}
|
||||||
@@ -660,7 +678,7 @@ public class CallResolver {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> ResolutionStatus checkValueArgumentTypes(CallResolutionContext<D> context) {
|
private <D extends CallableDescriptor, F extends D> ResolutionStatus checkValueArgumentTypes(CallResolutionContext<D, F> context) {
|
||||||
ResolutionStatus result = SUCCESS;
|
ResolutionStatus result = SUCCESS;
|
||||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : context.candidateCall.getValueArguments().entrySet()) {
|
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : context.candidateCall.getValueArguments().entrySet()) {
|
||||||
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
||||||
@@ -734,8 +752,8 @@ public class CallResolver {
|
|||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeResultAndReportErrors(
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeResultAndReportErrors(
|
||||||
BindingTrace trace,
|
BindingTrace trace,
|
||||||
TracingStrategy tracing,
|
TracingStrategy tracing,
|
||||||
Set<ResolvedCallImpl<D>> successfulCandidates,
|
Set<ResolvedCallWithTrace<D>> successfulCandidates,
|
||||||
Set<ResolvedCallImpl<D>> failedCandidates) {
|
Set<ResolvedCallWithTrace<D>> failedCandidates) {
|
||||||
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
|
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
|
||||||
|
|
||||||
if (successfulCandidates.size() > 0) {
|
if (successfulCandidates.size() > 0) {
|
||||||
@@ -756,8 +774,8 @@ public class CallResolver {
|
|||||||
// and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable"
|
// and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable"
|
||||||
// Used to be: weak errors. Generalized for future extensions
|
// Used to be: weak errors. Generalized for future extensions
|
||||||
for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) {
|
for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) {
|
||||||
Set<ResolvedCallImpl<D>> thisLevel = Sets.newLinkedHashSet();
|
Set<ResolvedCallWithTrace<D>> thisLevel = Sets.newLinkedHashSet();
|
||||||
for (ResolvedCallImpl<D> candidate : failedCandidates) {
|
for (ResolvedCallWithTrace<D> candidate : failedCandidates) {
|
||||||
if (severityLevel.contains(candidate.getStatus())) {
|
if (severityLevel.contains(candidate.getStatus())) {
|
||||||
thisLevel.add(candidate);
|
thisLevel.add(candidate);
|
||||||
}
|
}
|
||||||
@@ -777,7 +795,7 @@ public class CallResolver {
|
|||||||
|
|
||||||
assert false : "Should not be reachable, cause every status must belong to some level";
|
assert false : "Should not be reachable, cause every status must belong to some level";
|
||||||
|
|
||||||
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
|
Set<ResolvedCallWithTrace<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
|
||||||
if (noOverrides.size() != 1) {
|
if (noOverrides.size() != 1) {
|
||||||
tracing.noneApplicable(trace, noOverrides);
|
tracing.noneApplicable(trace, noOverrides);
|
||||||
tracing.recordAmbiguity(trace, noOverrides);
|
tracing.recordAmbiguity(trace, noOverrides);
|
||||||
@@ -787,7 +805,7 @@ public class CallResolver {
|
|||||||
failedCandidates = noOverrides;
|
failedCandidates = noOverrides;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResolvedCallImpl<D> failed = failedCandidates.iterator().next();
|
ResolvedCallWithTrace<D> failed = failedCandidates.iterator().next();
|
||||||
failed.getTrace().commit();
|
failed.getTrace().commit();
|
||||||
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
|
return OverloadResolutionResultsImpl.singleFailedCandidate(failed);
|
||||||
}
|
}
|
||||||
@@ -797,18 +815,18 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallImpl<D>> results) {
|
private static <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallWithTrace<D>> results) {
|
||||||
for (ResolvedCallImpl<D> result : results) {
|
for (ResolvedCallWithTrace<D> result : results) {
|
||||||
if (result.isDirty()) return false;
|
if (result.isDirty()) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(Set<ResolvedCallImpl<D>> candidates, boolean discriminateGenerics) {
|
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(Set<ResolvedCallWithTrace<D>> candidates, boolean discriminateGenerics) {
|
||||||
if (candidates.size() != 1) {
|
if (candidates.size() != 1) {
|
||||||
Set<ResolvedCallImpl<D>> cleanCandidates = Sets.newLinkedHashSet(candidates);
|
Set<ResolvedCallWithTrace<D>> cleanCandidates = Sets.newLinkedHashSet(candidates);
|
||||||
for (Iterator<ResolvedCallImpl<D>> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) {
|
for (Iterator<ResolvedCallWithTrace<D>> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) {
|
||||||
ResolvedCallImpl<D> candidate = iterator.next();
|
ResolvedCallWithTrace<D> candidate = iterator.next();
|
||||||
if (candidate.isDirty()) {
|
if (candidate.isDirty()) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
@@ -817,27 +835,28 @@ public class CallResolver {
|
|||||||
if (cleanCandidates.isEmpty()) {
|
if (cleanCandidates.isEmpty()) {
|
||||||
cleanCandidates = candidates;
|
cleanCandidates = candidates;
|
||||||
}
|
}
|
||||||
ResolvedCallImpl<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false);
|
ResolvedCallWithTrace<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, false);
|
||||||
if (maximallySpecific != null) {
|
if (maximallySpecific != null) {
|
||||||
return OverloadResolutionResultsImpl.success(maximallySpecific);
|
return OverloadResolutionResultsImpl.success(maximallySpecific);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discriminateGenerics) {
|
if (discriminateGenerics) {
|
||||||
ResolvedCallImpl<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true);
|
ResolvedCallWithTrace<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, true);
|
||||||
if (maximallySpecificGenericsDiscriminated != null) {
|
if (maximallySpecificGenericsDiscriminated != null) {
|
||||||
return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated);
|
return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT);
|
Set<ResolvedCallWithTrace<D>> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT);
|
||||||
|
|
||||||
return OverloadResolutionResultsImpl.ambiguity(noOverrides);
|
return OverloadResolutionResultsImpl.ambiguity(noOverrides);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ResolvedCallImpl<D> result = candidates.iterator().next();
|
ResolvedCallWithTrace<D> result = candidates.iterator().next();
|
||||||
|
|
||||||
TemporaryBindingTrace temporaryTrace = result.getTrace();
|
TemporaryBindingTrace temporaryTrace = result.getTrace();
|
||||||
temporaryTrace.commit();
|
temporaryTrace.commit();
|
||||||
|
|
||||||
return OverloadResolutionResultsImpl.success(result);
|
return OverloadResolutionResultsImpl.success(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -868,20 +887,19 @@ public class CallResolver {
|
|||||||
|
|
||||||
BindingTraceContext trace = new BindingTraceContext();
|
BindingTraceContext trace = new BindingTraceContext();
|
||||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(trace);
|
||||||
Set<ResolvedCallImpl<FunctionDescriptor>> calls = Sets.newLinkedHashSet();
|
Set<ResolvedCallWithTrace<FunctionDescriptor>> calls = Sets.newLinkedHashSet();
|
||||||
for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
|
for (ResolutionCandidate<FunctionDescriptor> candidate : candidates) {
|
||||||
ResolvedCallImpl<FunctionDescriptor> call = ResolvedCallImpl.create(candidate);
|
ResolvedCallImpl<FunctionDescriptor> call = ResolvedCallImpl.create(candidate, temporaryBindingTrace);
|
||||||
call.setTrace(temporaryBindingTrace);
|
|
||||||
calls.add(call);
|
calls.add(call);
|
||||||
}
|
}
|
||||||
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.<ResolvedCallImpl<FunctionDescriptor>>emptySet());
|
return computeResultAndReportErrors(trace, TracingStrategy.EMPTY, calls, Collections.<ResolvedCallWithTrace<FunctionDescriptor>>emptySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ResolutionCandidate<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
|
private List<ResolutionCandidate<FunctionDescriptor>> findCandidatesByExactSignature(JetScope scope, ReceiverDescriptor receiver,
|
||||||
String name, List<JetType> parameterTypes) {
|
String name, List<JetType> parameterTypes) {
|
||||||
List<ResolutionCandidate<FunctionDescriptor>> result = Lists.newArrayList();
|
List<ResolutionCandidate<FunctionDescriptor>> result = Lists.newArrayList();
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
Collection<ResolutionCandidate<FunctionDescriptor>> extensionFunctionDescriptors = ResolutionCandidate.convertCollection(scope.getFunctions(name));
|
Collection<ResolutionCandidate<FunctionDescriptor>> extensionFunctionDescriptors = ResolutionCandidate.convertCollection(scope.getFunctions(name), false);
|
||||||
List<ResolutionCandidate<FunctionDescriptor>> nonlocal = Lists.newArrayList();
|
List<ResolutionCandidate<FunctionDescriptor>> nonlocal = Lists.newArrayList();
|
||||||
List<ResolutionCandidate<FunctionDescriptor>> local = Lists.newArrayList();
|
List<ResolutionCandidate<FunctionDescriptor>> local = Lists.newArrayList();
|
||||||
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
|
TaskPrioritizer.splitLexicallyLocalDescriptors(extensionFunctionDescriptors, scope.getContainingDeclaration(), local, nonlocal);
|
||||||
@@ -891,7 +909,7 @@ public class CallResolver {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<ResolutionCandidate<FunctionDescriptor>> functionDescriptors = ResolutionCandidate.convertCollection(receiver.getType().getMemberScope().getFunctions(name));
|
Collection<ResolutionCandidate<FunctionDescriptor>> functionDescriptors = ResolutionCandidate.convertCollection(receiver.getType().getMemberScope().getFunctions(name), false);
|
||||||
if (lookupExactSignature(functionDescriptors, parameterTypes, result)) {
|
if (lookupExactSignature(functionDescriptors, parameterTypes, result)) {
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -900,7 +918,7 @@ public class CallResolver {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lookupExactSignature(ResolutionCandidate.convertCollection(scope.getFunctions(name)), parameterTypes, result);
|
lookupExactSignature(ResolutionCandidate.convertCollection(scope.getFunctions(name), false), parameterTypes, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-118
@@ -1,118 +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.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<D extends CallableDescriptor, R extends D> {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
CallResolutionContext<D> createCallContext(@NotNull ResolutionCandidate<D> candidate,
|
|
||||||
@NotNull ResolutionTask<D> task,
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull TracingStrategy tracing);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
Collection<ResolvedCallImpl<R>> transformResultCall(@NotNull CallResolutionContext<D> callResolutionContext,
|
|
||||||
@NotNull CallResolver callResolver,
|
|
||||||
@NotNull ResolutionTask<D> task);
|
|
||||||
|
|
||||||
CallTransformationStrategy<VariableDescriptor, VariableDescriptor>
|
|
||||||
PROPERTY_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy<VariableDescriptor, VariableDescriptor>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public CallResolutionContext<VariableDescriptor> createCallContext(@NotNull ResolutionCandidate<VariableDescriptor> candidate,
|
|
||||||
@NotNull ResolutionTask<VariableDescriptor> task, @NotNull BindingTrace trace, @NotNull TracingStrategy tracing) {
|
|
||||||
ResolvedCallImpl<VariableDescriptor> candidateCall = ResolvedCallImpl.create(candidate);
|
|
||||||
return new CallResolutionContext<VariableDescriptor>(candidateCall, task, trace, tracing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Collection<ResolvedCallImpl<VariableDescriptor>> transformResultCall(@NotNull CallResolutionContext<VariableDescriptor> context,
|
|
||||||
@NotNull CallResolver callResolver, @NotNull ResolutionTask<VariableDescriptor> task) {
|
|
||||||
return Collections.singleton(context.candidateCall);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CallTransformationStrategy<FunctionDescriptor, FunctionDescriptor>
|
|
||||||
FUNCTION_CALL_TRANSFORMATION_STRATEGY = new CallTransformationStrategy<FunctionDescriptor, FunctionDescriptor>() {
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public CallResolutionContext<FunctionDescriptor> createCallContext(@NotNull ResolutionCandidate<FunctionDescriptor> candidate,
|
|
||||||
@NotNull ResolutionTask<FunctionDescriptor> task,
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull TracingStrategy tracing) {
|
|
||||||
if (candidate.getDescriptor() instanceof FunctionDescriptor) {
|
|
||||||
return new CallResolutionContext<FunctionDescriptor>(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<JetExpression> getFunctionLiteralArguments() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public List<JetTypeProjection> getTypeArguments() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JetTypeArgumentList getTypeArgumentList() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return new CallResolutionContext<FunctionDescriptor>(ResolvedCallImpl.create(candidate), task, trace, tracing, propertyCall);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Collection<ResolvedCallImpl<FunctionDescriptor>> transformResultCall(@NotNull CallResolutionContext<FunctionDescriptor> context,
|
|
||||||
@NotNull CallResolver callResolver, @NotNull ResolutionTask<FunctionDescriptor> 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<FunctionDescriptor> results =
|
|
||||||
callResolver.resolveCallWithGivenName(basicResolutionContext, task.reference, "invoke");
|
|
||||||
return ((OverloadResolutionResultsImpl<FunctionDescriptor>)results).getResultingCalls();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* 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.base.Function;
|
||||||
|
import com.google.common.collect.Collections2;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
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.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallTransformer treats specially 'variable as function' call case, other cases keeps unchanged (base realization).
|
||||||
|
*
|
||||||
|
* For the call 'b.foo(1)' where foo is a variable that has method 'invoke' (for example of function type)
|
||||||
|
* CallTransformer creates two contexts, two calls in each, and performs second ('invoke') call resolution:
|
||||||
|
*
|
||||||
|
* context#1. calls: 'b.foo' 'invoke(1)'
|
||||||
|
* context#2. calls: 'foo' 'b.invoke(1)'
|
||||||
|
*
|
||||||
|
* If success VariableAsFunctionResolvedCall is created.
|
||||||
|
*
|
||||||
|
* @author svtk
|
||||||
|
*/
|
||||||
|
public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||||
|
private CallTransformer() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns two contexts for 'variable as function' case (in FUNCTION_CALL_TRANSFORMER), one context otherwise
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Collection<CallResolutionContext<D, F>> createCallContexts(@NotNull ResolutionCandidate<D> candidate,
|
||||||
|
@NotNull ResolutionTask<D, F> task,
|
||||||
|
@NotNull TemporaryBindingTrace temporaryTrace) {
|
||||||
|
|
||||||
|
ResolvedCallImpl<D> candidateCall = ResolvedCallImpl.create(candidate, temporaryTrace);
|
||||||
|
return Collections.singleton(CallResolutionContext.create(candidateCall, task, temporaryTrace, task.tracing));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns collection of resolved calls for 'invoke' for 'variable as function' case (in FUNCTION_CALL_TRANSFORMER),
|
||||||
|
* the resolved call from callResolutionContext otherwise
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Collection<ResolvedCallWithTrace<F>> transformCall(@NotNull CallResolutionContext<D, F> callResolutionContext,
|
||||||
|
@NotNull CallResolver callResolver,
|
||||||
|
@NotNull ResolutionTask<D, F> task) {
|
||||||
|
|
||||||
|
return Collections.singleton((ResolvedCallWithTrace<F>)callResolutionContext.candidateCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static CallTransformer<VariableDescriptor, VariableDescriptor> PROPERTY_CALL_TRANSFORMER = new CallTransformer<VariableDescriptor, VariableDescriptor>();
|
||||||
|
|
||||||
|
public static CallTransformer<CallableDescriptor, FunctionDescriptor> FUNCTION_CALL_TRANSFORMER = new CallTransformer<CallableDescriptor, FunctionDescriptor>() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<CallResolutionContext<CallableDescriptor, FunctionDescriptor>> createCallContexts(@NotNull ResolutionCandidate<CallableDescriptor> candidate,
|
||||||
|
@NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task, @NotNull TemporaryBindingTrace temporaryTrace) {
|
||||||
|
|
||||||
|
if (candidate.getDescriptor() instanceof FunctionDescriptor) {
|
||||||
|
return super.createCallContexts(candidate, task, temporaryTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert candidate.getDescriptor() instanceof VariableDescriptor;
|
||||||
|
|
||||||
|
boolean hasReceiver = candidate.getReceiverArgument().exists();
|
||||||
|
Call variableCall = stripCallArguments(task);
|
||||||
|
if (!hasReceiver) {
|
||||||
|
CallResolutionContext<CallableDescriptor, FunctionDescriptor> context = CallResolutionContext.create(
|
||||||
|
ResolvedCallImpl.create(candidate, temporaryTrace), task, temporaryTrace, task.tracing, variableCall);
|
||||||
|
return Collections.singleton(context);
|
||||||
|
}
|
||||||
|
Call variableCallWithoutReceiver = stripReceiver(variableCall);
|
||||||
|
CallResolutionContext<CallableDescriptor, FunctionDescriptor> contextWithReceiver = createContextWithChainedTrace(
|
||||||
|
candidate, variableCall, temporaryTrace, task);
|
||||||
|
|
||||||
|
ResolutionCandidate<CallableDescriptor> candidateWithoutReceiver = ResolutionCandidate.create(
|
||||||
|
candidate.getDescriptor(), candidate.getThisObject(), ReceiverDescriptor.NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
|
||||||
|
|
||||||
|
CallResolutionContext<CallableDescriptor, FunctionDescriptor> contextWithoutReceiver = createContextWithChainedTrace(
|
||||||
|
candidateWithoutReceiver, variableCallWithoutReceiver, temporaryTrace, task);
|
||||||
|
|
||||||
|
contextWithoutReceiver.receiverForVariableAsFunctionSecondCall = variableCall.getExplicitReceiver();
|
||||||
|
|
||||||
|
return Lists.newArrayList(contextWithReceiver, contextWithoutReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CallResolutionContext<CallableDescriptor, FunctionDescriptor> createContextWithChainedTrace(ResolutionCandidate<CallableDescriptor> candidate,
|
||||||
|
Call call, TemporaryBindingTrace temporaryTrace, ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
|
||||||
|
|
||||||
|
ChainedTemporaryBindingTrace chainedTrace = ChainedTemporaryBindingTrace.create(temporaryTrace);
|
||||||
|
ResolvedCallImpl<CallableDescriptor> resolvedCall = ResolvedCallImpl.create(candidate, chainedTrace);
|
||||||
|
return CallResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Call stripCallArguments(@NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
|
||||||
|
return new DelegatingCall(task.call) {
|
||||||
|
@Override
|
||||||
|
public JetValueArgumentList getValueArgumentList() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<? extends ValueArgument> getValueArguments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<JetExpression> getFunctionLiteralArguments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<JetTypeProjection> getTypeArguments() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetTypeArgumentList getTypeArgumentList() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Call stripReceiver(@NotNull Call variableCall) {
|
||||||
|
return new DelegatingCall(variableCall) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getExplicitReceiver() {
|
||||||
|
return ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<ResolvedCallWithTrace<FunctionDescriptor>> transformCall(@NotNull final CallResolutionContext<CallableDescriptor, FunctionDescriptor> context,
|
||||||
|
@NotNull CallResolver callResolver, @NotNull final ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
|
||||||
|
|
||||||
|
final CallableDescriptor descriptor = context.candidateCall.getCandidateDescriptor();
|
||||||
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
|
return super.transformCall(context, callResolver, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert descriptor instanceof VariableDescriptor;
|
||||||
|
JetType returnType = descriptor.getReturnType();
|
||||||
|
if (returnType == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ResolvedCallWithTrace<VariableDescriptor> variableResolvedCall = (ResolvedCallWithTrace)context.candidateCall;
|
||||||
|
|
||||||
|
Call functionCall = createFunctionCall(context, task, returnType);
|
||||||
|
|
||||||
|
final TemporaryBindingTrace variableCallTrace = context.candidateCall.getTrace();
|
||||||
|
BasicResolutionContext basicResolutionContext = BasicResolutionContext.create(variableCallTrace, context.scope, functionCall, context.expectedType, context.dataFlowInfo);
|
||||||
|
|
||||||
|
// 'invoke' call resolve
|
||||||
|
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveCallWithGivenName(basicResolutionContext, task.reference, "invoke");
|
||||||
|
Collection<ResolvedCallWithTrace<FunctionDescriptor>> calls = ((OverloadResolutionResultsImpl<FunctionDescriptor>)results).getResultingCalls();
|
||||||
|
|
||||||
|
return Collections2.transform(calls, new Function<ResolvedCallWithTrace<FunctionDescriptor>, ResolvedCallWithTrace<FunctionDescriptor>>() {
|
||||||
|
@Override
|
||||||
|
public ResolvedCallWithTrace<FunctionDescriptor> apply(ResolvedCallWithTrace<FunctionDescriptor> functionResolvedCall) {
|
||||||
|
return new VariableAsFunctionResolvedCall(functionResolvedCall, variableResolvedCall);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Call createFunctionCall(final CallResolutionContext<CallableDescriptor, FunctionDescriptor> context,
|
||||||
|
final ResolutionTask<CallableDescriptor, FunctionDescriptor> task, JetType returnType) {
|
||||||
|
|
||||||
|
final ExpressionReceiver receiverFromVariable = new ExpressionReceiver(task.reference, returnType);
|
||||||
|
final JetSimpleNameExpression invokeExpression = (JetSimpleNameExpression) JetPsiFactory.createExpression(
|
||||||
|
task.call.getCallElement().getProject(), "invoke");
|
||||||
|
|
||||||
|
return new CallForImplicitInvoke(task.call) {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getExplicitReceiver() {
|
||||||
|
return context.receiverForVariableAsFunctionSecondCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getThisObject() {
|
||||||
|
return receiverFromVariable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetExpression getCalleeExpression() {
|
||||||
|
return invokeExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiElement getCallElement() {
|
||||||
|
if (task.call.getCallElement() instanceof JetCallElement) {
|
||||||
|
//to report errors properly
|
||||||
|
JetValueArgumentList list = ((JetCallElement)task.call.getCallElement()).getValueArgumentList();
|
||||||
|
if (list != null) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return invokeExpression;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static class CallForImplicitInvoke extends DelegatingCall {
|
||||||
|
public CallForImplicitInvoke(@NotNull Call delegate) {
|
||||||
|
super(delegate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -26,7 +26,7 @@ import java.util.Collection;
|
|||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
public interface MemberPrioritizer<D extends CallableDescriptor> {
|
public interface CallableDescriptorCollector<D extends CallableDescriptor> {
|
||||||
@NotNull
|
@NotNull
|
||||||
Collection<D> getNonExtensionsByName(JetScope scope, String name);
|
Collection<D> getNonExtensionsByName(JetScope scope, String name);
|
||||||
|
|
||||||
@@ -34,5 +34,5 @@ public interface MemberPrioritizer<D extends CallableDescriptor> {
|
|||||||
Collection<D> getMembersByName(@NotNull JetType receiver, String name);
|
Collection<D> getMembersByName(@NotNull JetType receiver, String name);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Collection<D> getExtensionsByName(JetScope scope, String name);
|
Collection<D> getNonMembersByName(JetScope scope, String name);
|
||||||
}
|
}
|
||||||
+23
-47
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -34,11 +33,9 @@ import java.util.*;
|
|||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class MemberPrioritizers {
|
public class CallableDescriptorCollectors {
|
||||||
|
|
||||||
|
|
||||||
/*package*/ static MemberPrioritizer<FunctionDescriptor> FUNCTION_TASK_PRIORITIZER = new MemberPrioritizer<FunctionDescriptor>() {
|
|
||||||
|
|
||||||
|
/*package*/ static CallableDescriptorCollector<FunctionDescriptor> FUNCTIONS = new CallableDescriptorCollector<FunctionDescriptor>() {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@@ -51,8 +48,6 @@ public class MemberPrioritizers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addConstructors(scope, name, functions);
|
addConstructors(scope, name, functions);
|
||||||
|
|
||||||
addVariableAsFunction(scope, name, functions, false);
|
|
||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,22 +57,13 @@ public class MemberPrioritizers {
|
|||||||
JetScope receiverScope = receiverType.getMemberScope();
|
JetScope receiverScope = receiverType.getMemberScope();
|
||||||
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
|
Set<FunctionDescriptor> members = Sets.newHashSet(receiverScope.getFunctions(name));
|
||||||
addConstructors(receiverScope, name, members);
|
addConstructors(receiverScope, name, members);
|
||||||
addVariableAsFunction(receiverScope, name, members, false);
|
|
||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<FunctionDescriptor> getExtensionsByName(JetScope scope, String name) {
|
public Collection<FunctionDescriptor> getNonMembersByName(JetScope scope, String name) {
|
||||||
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
|
return scope.getFunctions(name);
|
||||||
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
|
|
||||||
FunctionDescriptor descriptor = iterator.next();
|
|
||||||
if (!descriptor.getReceiverParameter().exists()) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addVariableAsFunction(scope, name, extensionFunctions, true);
|
|
||||||
return extensionFunctions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
|
private void addConstructors(JetScope scope, String name, Collection<FunctionDescriptor> functions) {
|
||||||
@@ -87,25 +73,9 @@ public class MemberPrioritizers {
|
|||||||
functions.addAll(classDescriptor.getConstructors());
|
functions.addAll(classDescriptor.getConstructors());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
|
|
||||||
VariableDescriptor variable = scope.getLocalVariable(name);
|
|
||||||
if (variable == null) {
|
|
||||||
variable = DescriptorUtils.filterNonExtensionProperty(scope.getProperties(name));
|
|
||||||
}
|
|
||||||
if (variable != null) {
|
|
||||||
JetType outType = variable.getType();
|
|
||||||
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
|
|
||||||
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
|
|
||||||
if ((functionDescriptor.getReceiverParameter().exists()) == receiverNeeded) {
|
|
||||||
functions.add(functionDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*package*/ static MemberPrioritizer<VariableDescriptor> VARIABLE_TASK_PRIORITIZER = new MemberPrioritizer<VariableDescriptor>() {
|
/*package*/ static CallableDescriptorCollector<VariableDescriptor> VARIABLES = new CallableDescriptorCollector<VariableDescriptor>() {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@@ -126,17 +96,19 @@ public class MemberPrioritizers {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, String name) {
|
||||||
return Collections2.filter(scope.getProperties(name), new Predicate<VariableDescriptor>() {
|
Collection<VariableDescriptor> result = Sets.newLinkedHashSet();
|
||||||
@Override
|
|
||||||
public boolean apply(@Nullable VariableDescriptor variableDescriptor) {
|
VariableDescriptor localVariable = scope.getLocalVariable(name);
|
||||||
return (variableDescriptor != null) && variableDescriptor.getReceiverParameter().exists();
|
if (localVariable != null) {
|
||||||
}
|
result.add(localVariable);
|
||||||
});
|
}
|
||||||
|
result.addAll(scope.getProperties(name));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*package*/ static MemberPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new MemberPrioritizer<VariableDescriptor>() {
|
/*package*/ static CallableDescriptorCollector<VariableDescriptor> PROPERTIES = new CallableDescriptorCollector<VariableDescriptor>() {
|
||||||
private Collection<VariableDescriptor> filterProperties(Collection<? extends VariableDescriptor> variableDescriptors) {
|
private Collection<VariableDescriptor> filterProperties(Collection<? extends VariableDescriptor> variableDescriptors) {
|
||||||
ArrayList<VariableDescriptor> properties = Lists.newArrayList();
|
ArrayList<VariableDescriptor> properties = Lists.newArrayList();
|
||||||
for (VariableDescriptor descriptor : variableDescriptors) {
|
for (VariableDescriptor descriptor : variableDescriptors) {
|
||||||
@@ -150,19 +122,23 @@ public class MemberPrioritizers {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
public Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||||
return filterProperties(VARIABLE_TASK_PRIORITIZER.getNonExtensionsByName(scope, name));
|
return filterProperties(VARIABLES.getNonExtensionsByName(scope, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, String name) {
|
public Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, String name) {
|
||||||
return filterProperties(VARIABLE_TASK_PRIORITIZER.getMembersByName(receiver, name));
|
return filterProperties(VARIABLES.getMembersByName(receiver, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
public Collection<VariableDescriptor> getNonMembersByName(JetScope scope, String name) {
|
||||||
return filterProperties(VARIABLE_TASK_PRIORITIZER.getExtensionsByName(scope, name));
|
return filterProperties(VARIABLES.getNonMembersByName(scope, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*package*/ static List<CallableDescriptorCollector<? extends CallableDescriptor>> FUNCTIONS_AND_VARIABLES = Lists.newArrayList(
|
||||||
|
FUNCTIONS, VARIABLES);
|
||||||
}
|
}
|
||||||
@@ -48,6 +48,12 @@ public class DelegatingCall implements Call {
|
|||||||
return delegate.getExplicitReceiver();
|
return delegate.getExplicitReceiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getThisObject() {
|
||||||
|
return delegate.getThisObject();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetExpression getCalleeExpression() {
|
public JetExpression getCalleeExpression() {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author svtk
|
||||||
|
*/
|
||||||
|
public enum ExplicitReceiverKind {
|
||||||
|
RECEIVER_ARGUMENT,
|
||||||
|
THIS_OBJECT,
|
||||||
|
NO_EXPLICIT_RECEIVER,
|
||||||
|
|
||||||
|
// A very special case.
|
||||||
|
// In a call 'b.foo(1)' where class 'Foo' has an extension member 'fun B.invoke(Int)' function 'invoke' has two explicit receivers:
|
||||||
|
// 'b' (as receiver argument) and 'foo' (as this object).
|
||||||
|
BOTH_RECEIVERS;
|
||||||
|
|
||||||
|
public boolean isReceiver() {
|
||||||
|
return this == RECEIVER_ARGUMENT || this == BOTH_RECEIVERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThisObject() {
|
||||||
|
return this == THIS_OBJECT || this == BOTH_RECEIVERS;
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-9
@@ -27,42 +27,42 @@ import java.util.Collections;
|
|||||||
*/
|
*/
|
||||||
/*package*/ class OverloadResolutionResultsImpl<D extends CallableDescriptor> implements OverloadResolutionResults<D> {
|
/*package*/ class OverloadResolutionResultsImpl<D extends CallableDescriptor> implements OverloadResolutionResults<D> {
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> success(@NotNull ResolvedCallImpl<D> descriptor) {
|
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> success(@NotNull ResolvedCallWithTrace<D> descriptor) {
|
||||||
return new OverloadResolutionResultsImpl<D>(Code.SUCCESS, Collections.singleton(descriptor));
|
return new OverloadResolutionResultsImpl<D>(Code.SUCCESS, Collections.singleton(descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> nameNotFound() {
|
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> nameNotFound() {
|
||||||
return new OverloadResolutionResultsImpl<D>(Code.NAME_NOT_FOUND, Collections.<ResolvedCallImpl<D>>emptyList());
|
return new OverloadResolutionResultsImpl<D>(Code.NAME_NOT_FOUND, Collections.<ResolvedCallWithTrace<D>>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> singleFailedCandidate(ResolvedCallImpl<D> candidate) {
|
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> singleFailedCandidate(ResolvedCallWithTrace<D> candidate) {
|
||||||
return new OverloadResolutionResultsImpl<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
|
return new OverloadResolutionResultsImpl<D>(Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH, Collections.singleton(candidate));
|
||||||
}
|
}
|
||||||
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> manyFailedCandidates(Collection<ResolvedCallImpl<D>> failedCandidates) {
|
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> manyFailedCandidates(Collection<ResolvedCallWithTrace<D>> failedCandidates) {
|
||||||
return new OverloadResolutionResultsImpl<D>(Code.MANY_FAILED_CANDIDATES, failedCandidates);
|
return new OverloadResolutionResultsImpl<D>(Code.MANY_FAILED_CANDIDATES, failedCandidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> ambiguity(Collection<ResolvedCallImpl<D>> descriptors) {
|
public static <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> ambiguity(Collection<ResolvedCallWithTrace<D>> descriptors) {
|
||||||
return new OverloadResolutionResultsImpl<D>(Code.AMBIGUITY, descriptors);
|
return new OverloadResolutionResultsImpl<D>(Code.AMBIGUITY, descriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Collection<ResolvedCallImpl<D>> results;
|
private final Collection<ResolvedCallWithTrace<D>> results;
|
||||||
private final Code resultCode;
|
private final Code resultCode;
|
||||||
|
|
||||||
private OverloadResolutionResultsImpl(@NotNull Code resultCode, @NotNull Collection<ResolvedCallImpl<D>> results) {
|
private OverloadResolutionResultsImpl(@NotNull Code resultCode, @NotNull Collection<ResolvedCallWithTrace<D>> results) {
|
||||||
this.results = results;
|
this.results = results;
|
||||||
this.resultCode = resultCode;
|
this.resultCode = resultCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public Collection<ResolvedCallImpl<D>> getResultingCalls() {
|
public Collection<ResolvedCallWithTrace<D>> getResultingCalls() {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public ResolvedCallImpl<D> getResultingCall() {
|
public ResolvedCallWithTrace<D> getResultingCall() {
|
||||||
assert isSingleResult();
|
assert isSingleResult();
|
||||||
return results.iterator().next();
|
return results.iterator().next();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -30,9 +30,9 @@ import java.util.Collection;
|
|||||||
public class OverloadResolutionResultsUtil {
|
public class OverloadResolutionResultsUtil {
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <D extends CallableDescriptor> OverloadResolutionResults<D> ambiguity(OverloadResolutionResults<D> results1, OverloadResolutionResults<D> results2) {
|
public static <D extends CallableDescriptor> OverloadResolutionResults<D> ambiguity(OverloadResolutionResults<D> results1, OverloadResolutionResults<D> results2) {
|
||||||
Collection<ResolvedCallImpl<D>> resultingCalls = Lists.newArrayList();
|
Collection<ResolvedCallWithTrace<D>> resultingCalls = Lists.newArrayList();
|
||||||
resultingCalls.addAll((Collection<ResolvedCallImpl<D>>) results1.getResultingCalls());
|
resultingCalls.addAll((Collection<ResolvedCallWithTrace<D>>) results1.getResultingCalls());
|
||||||
resultingCalls.addAll((Collection<ResolvedCallImpl<D>>) results2.getResultingCalls());
|
resultingCalls.addAll((Collection<ResolvedCallWithTrace<D>>) results2.getResultingCalls());
|
||||||
return OverloadResolutionResultsImpl.ambiguity(resultingCalls);
|
return OverloadResolutionResultsImpl.ambiguity(resultingCalls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -39,23 +39,23 @@ import java.util.Set;
|
|||||||
public class OverloadingConflictResolver {
|
public class OverloadingConflictResolver {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public <D extends CallableDescriptor> ResolvedCallImpl<D> findMaximallySpecific(Set<ResolvedCallImpl<D>> candidates, boolean discriminateGenericDescriptors) {
|
public <D extends CallableDescriptor> ResolvedCallWithTrace<D> findMaximallySpecific(Set<ResolvedCallWithTrace<D>> candidates, boolean discriminateGenericDescriptors) {
|
||||||
// Different autocasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
|
// Different autocasts may lead to the same candidate descriptor wrapped into different ResolvedCallImpl objects
|
||||||
Set<ResolvedCallImpl<D>> maximallySpecific = new THashSet<ResolvedCallImpl<D>>(new TObjectHashingStrategy<ResolvedCallImpl<D>>() {
|
Set<ResolvedCallWithTrace<D>> maximallySpecific = new THashSet<ResolvedCallWithTrace<D>>(new TObjectHashingStrategy<ResolvedCallWithTrace<D>>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(ResolvedCallImpl<D> o1, ResolvedCallImpl<D> o2) {
|
public boolean equals(ResolvedCallWithTrace<D> o1, ResolvedCallWithTrace<D> o2) {
|
||||||
return o1 == null ? o2 == null : o1.getResultingDescriptor().equals(o2.getResultingDescriptor());
|
return o1 == null ? o2 == null : o1.getResultingDescriptor().equals(o2.getResultingDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int computeHashCode(ResolvedCallImpl<D> object) {
|
public int computeHashCode(ResolvedCallWithTrace<D> object) {
|
||||||
return object == null ? 0 : object.getResultingDescriptor().hashCode();
|
return object == null ? 0 : object.getResultingDescriptor().hashCode();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
meLoop:
|
meLoop:
|
||||||
for (ResolvedCallImpl<D> candidateCall : candidates) {
|
for (ResolvedCallWithTrace<D> candidateCall : candidates) {
|
||||||
D me = candidateCall.getResultingDescriptor();
|
D me = candidateCall.getResultingDescriptor();
|
||||||
for (ResolvedCallImpl<D> otherCall : candidates) {
|
for (ResolvedCallWithTrace<D> otherCall : candidates) {
|
||||||
D other = otherCall.getResultingDescriptor();
|
D other = otherCall.getResultingDescriptor();
|
||||||
if (other == me) continue;
|
if (other == me) continue;
|
||||||
if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) {
|
if (!moreSpecific(me, other, discriminateGenericDescriptors) || moreSpecific(other, me, discriminateGenericDescriptors)) {
|
||||||
@@ -65,7 +65,7 @@ public class OverloadingConflictResolver {
|
|||||||
maximallySpecific.add(candidateCall);
|
maximallySpecific.add(candidateCall);
|
||||||
}
|
}
|
||||||
if (maximallySpecific.size() == 1) {
|
if (maximallySpecific.size() == 1) {
|
||||||
ResolvedCallImpl<D> result = maximallySpecific.iterator().next();
|
ResolvedCallWithTrace<D> result = maximallySpecific.iterator().next();
|
||||||
result.getTrace().commit();
|
result.getTrace().commit();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-8
@@ -18,12 +18,16 @@ package org.jetbrains.jet.lang.resolve.calls;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.Call;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.ExplicitReceiverKind.NO_EXPLICIT_RECEIVER;
|
||||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,15 +35,31 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
*/
|
*/
|
||||||
public class ResolutionCandidate<D extends CallableDescriptor> {
|
public class ResolutionCandidate<D extends CallableDescriptor> {
|
||||||
private final D candidateDescriptor;
|
private final D candidateDescriptor;
|
||||||
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
|
private ReceiverDescriptor thisObject; // receiver object of a method
|
||||||
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
|
private ReceiverDescriptor receiverArgument; // receiver of an extension function
|
||||||
|
private ExplicitReceiverKind explicitReceiverKind;
|
||||||
|
private Boolean isSafeCall;
|
||||||
|
|
||||||
private ResolutionCandidate(@NotNull D descriptor) {
|
private ResolutionCandidate(@NotNull D descriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument,
|
||||||
candidateDescriptor = descriptor;
|
@NotNull ExplicitReceiverKind explicitReceiverKind, @Nullable Boolean isSafeCall) {
|
||||||
|
this.candidateDescriptor = descriptor;
|
||||||
|
this.thisObject = thisObject;
|
||||||
|
this.receiverArgument = receiverArgument;
|
||||||
|
this.explicitReceiverKind = explicitReceiverKind;
|
||||||
|
this.isSafeCall = isSafeCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor) {
|
/*package*/ static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor) {
|
||||||
return new ResolutionCandidate<D>(descriptor);
|
return new ResolutionCandidate<D>(descriptor, NO_RECEIVER, NO_RECEIVER, NO_EXPLICIT_RECEIVER, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor, boolean isSafeCall) {
|
||||||
|
return create(descriptor, NO_RECEIVER, NO_RECEIVER, NO_EXPLICIT_RECEIVER, isSafeCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(@NotNull D descriptor, @NotNull ReceiverDescriptor thisObject,
|
||||||
|
@NotNull ReceiverDescriptor receiverArgument, @NotNull ExplicitReceiverKind explicitReceiverKind, boolean isSafeCall) {
|
||||||
|
return new ResolutionCandidate<D>(descriptor, thisObject, receiverArgument, explicitReceiverKind, isSafeCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
|
public void setThisObject(@NotNull ReceiverDescriptor thisObject) {
|
||||||
@@ -50,6 +70,10 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
|
|||||||
this.receiverArgument = receiverArgument;
|
this.receiverArgument = receiverArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setExplicitReceiverKind(@NotNull ExplicitReceiverKind explicitReceiverKind) {
|
||||||
|
this.explicitReceiverKind = explicitReceiverKind;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public D getDescriptor() {
|
public D getDescriptor() {
|
||||||
return candidateDescriptor;
|
return candidateDescriptor;
|
||||||
@@ -66,12 +90,26 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <D extends CallableDescriptor> List<ResolutionCandidate<D>> convertCollection(@NotNull Collection<? extends D> descriptors) {
|
public ExplicitReceiverKind getExplicitReceiverKind() {
|
||||||
|
return explicitReceiverKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static <D extends CallableDescriptor> List<ResolutionCandidate<D>> convertCollection(@NotNull Collection<? extends D> descriptors, boolean isSafeCall) {
|
||||||
List<ResolutionCandidate<D>> result = Lists.newArrayList();
|
List<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||||
for (D descriptor : descriptors) {
|
for (D descriptor : descriptors) {
|
||||||
result.add(create(descriptor));
|
result.add(create(descriptor, isSafeCall));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSafeCall(boolean safeCall) {
|
||||||
|
assert isSafeCall == null;
|
||||||
|
isSafeCall = safeCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSafeCall() {
|
||||||
|
assert isSafeCall != null;
|
||||||
|
return isSafeCall;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import java.util.Map;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ResolutionDebugInfo {
|
public class ResolutionDebugInfo {
|
||||||
public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor>>> TASKS = Slices.createSimpleSlice();
|
public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor, ?>>> TASKS = Slices.createSimpleSlice();
|
||||||
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
|
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
|
||||||
|
|
||||||
public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, StringBuilder> ERRORS = Slices.createSimpleSlice();
|
public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, StringBuilder> ERRORS = Slices.createSimpleSlice();
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls;
|
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.google.common.collect.Sets;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
@@ -39,6 +37,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
@@ -48,9 +47,9 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
|||||||
*
|
*
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ResolutionTask<D extends CallableDescriptor> extends ResolutionContext {
|
public class ResolutionTask<D extends CallableDescriptor, F extends D> extends ResolutionContext {
|
||||||
private final Collection<ResolutionCandidate<D>> candidates;
|
private final Collection<ResolutionCandidate<D>> candidates;
|
||||||
private final Multimap<ResolutionCandidate<D>, ResolvedCallImpl<D>> resolvedCallMap = LinkedHashMultimap.create();
|
private final Set<ResolvedCallWithTrace<F>> resolvedCalls = Sets.newLinkedHashSet();
|
||||||
/*package*/ final JetReferenceExpression reference;
|
/*package*/ final JetReferenceExpression reference;
|
||||||
private DescriptorCheckStrategy checkingStrategy;
|
private DescriptorCheckStrategy checkingStrategy;
|
||||||
|
|
||||||
@@ -71,8 +70,8 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Multimap<ResolutionCandidate<D>, ResolvedCallImpl<D>> getResolvedCallMap() {
|
public Set<ResolvedCallWithTrace<F>> getResolvedCalls() {
|
||||||
return resolvedCallMap;
|
return resolvedCalls;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
|
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
|
||||||
@@ -86,8 +85,8 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResolutionTask<D> withTrace(BindingTrace newTrace) {
|
public ResolutionTask<D, F> withTrace(BindingTrace newTrace) {
|
||||||
ResolutionTask<D> newTask = new ResolutionTask<D>(candidates, reference, newTrace, scope, call, expectedType, dataFlowInfo);
|
ResolutionTask<D, F> newTask = new ResolutionTask<D, F>(candidates, reference, newTrace, scope, call, expectedType, dataFlowInfo);
|
||||||
newTask.setCheckingStrategy(checkingStrategy);
|
newTask.setCheckingStrategy(checkingStrategy);
|
||||||
return newTask;
|
return newTask;
|
||||||
}
|
}
|
||||||
@@ -98,22 +97,19 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
|
|
||||||
public final TracingStrategy tracing = new TracingStrategy() {
|
public final TracingStrategy tracing = new TracingStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {
|
public <D extends CallableDescriptor> void bindResolvedCall(@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall) {
|
||||||
D descriptor = resolvedCall.getCandidateDescriptor();
|
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||||
// if (descriptor instanceof VariableAsFunctionDescriptor) {
|
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||||
// VariableAsFunctionDescriptor variableAsFunctionDescriptor = (VariableAsFunctionDescriptor) descriptor;
|
descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getResultingDescriptor();
|
||||||
// trace.record(REFERENCE_TARGET, reference, variableAsFunctionDescriptor.getVariableDescriptor());
|
}
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// }
|
|
||||||
trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall);
|
|
||||||
trace.record(REFERENCE_TARGET, reference, descriptor);
|
trace.record(REFERENCE_TARGET, reference, descriptor);
|
||||||
|
trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates) {
|
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallWithTrace<D>> candidates) {
|
||||||
Collection<D> descriptors = Sets.newHashSet();
|
Collection<D> descriptors = Sets.newHashSet();
|
||||||
for (ResolvedCallImpl<D> candidate : candidates) {
|
for (ResolvedCallWithTrace<D> candidate : candidates) {
|
||||||
descriptors.add(candidate.getCandidateDescriptor());
|
descriptors.add(candidate.getCandidateDescriptor());
|
||||||
}
|
}
|
||||||
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
|
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, descriptors);
|
||||||
@@ -155,7 +151,14 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void noReceiverAllowed(@NotNull BindingTrace trace) {
|
public void noReceiverAllowed(@NotNull BindingTrace trace) {
|
||||||
trace.report(NO_RECEIVER_ADMITTED.on(reference));
|
if (reference instanceof JetSimpleNameExpression) {
|
||||||
|
//todo temporary hack
|
||||||
|
//should be stored that the reference is unresolved (and not trace the candidate descriptor)
|
||||||
|
trace.report(UNRESOLVED_REFERENCE.on(reference));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(NO_RECEIVER_ADMITTED.on(reference));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -170,12 +173,12 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
|
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors) {
|
||||||
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors));
|
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
|
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors) {
|
||||||
trace.report(NONE_APPLICABLE.on(reference, descriptors));
|
trace.report(NONE_APPLICABLE.on(reference, descriptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,9 +194,9 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) {
|
||||||
ASTNode callOperationNode = call.getCallOperationNode();
|
ASTNode callOperationNode = call.getCallOperationNode();
|
||||||
if (callOperationNode != null) {
|
if (callOperationNode != null && !isCallForImplicitInvoke) {
|
||||||
trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
|
trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -233,8 +236,7 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor) {
|
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor) {
|
||||||
JetExpression expression = call.getCalleeExpression();
|
trace.report(INVISIBLE_MEMBER.on(call.getCallElement(), descriptor, descriptor.getContainingDeclaration()));
|
||||||
trace.report(INVISIBLE_MEMBER.on(expression != null ? expression : call.getCallElement(), descriptor, descriptor.getContainingDeclaration()));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-7
@@ -21,9 +21,12 @@ import com.google.common.base.Predicates;
|
|||||||
import com.google.common.collect.Collections2;
|
import com.google.common.collect.Collections2;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -31,16 +34,17 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
public class ResolutionTaskHolder<D extends CallableDescriptor> {
|
public class ResolutionTaskHolder<D extends CallableDescriptor, F extends D> {
|
||||||
private final JetReferenceExpression reference;
|
private final JetReferenceExpression reference;
|
||||||
private final BasicResolutionContext basicResolutionContext;
|
private final BasicResolutionContext basicResolutionContext;
|
||||||
private final Predicate<ResolutionCandidate<D>> visibleStrategy;
|
private final Predicate<ResolutionCandidate<D>> visibleStrategy;
|
||||||
|
private final boolean isSafeCall;
|
||||||
|
|
||||||
private final Collection<Collection<ResolutionCandidate<D>>> localExtensions = Sets.newLinkedHashSet();
|
private final Collection<Collection<ResolutionCandidate<D>>> localExtensions = Sets.newLinkedHashSet();
|
||||||
private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
|
private final Collection<Collection<ResolutionCandidate<D>>> members = Sets.newLinkedHashSet();
|
||||||
private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
|
private final Collection<Collection<ResolutionCandidate<D>>> nonLocalExtensions = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
private List<ResolutionTask<D>> tasks = null;
|
private List<ResolutionTask<D, F>> tasks = null;
|
||||||
|
|
||||||
public ResolutionTaskHolder(@NotNull JetReferenceExpression reference,
|
public ResolutionTaskHolder(@NotNull JetReferenceExpression reference,
|
||||||
@NotNull BasicResolutionContext basicResolutionContext,
|
@NotNull BasicResolutionContext basicResolutionContext,
|
||||||
@@ -48,27 +52,35 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
|
|||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
this.basicResolutionContext = basicResolutionContext;
|
this.basicResolutionContext = basicResolutionContext;
|
||||||
this.visibleStrategy = visibleStrategy;
|
this.visibleStrategy = visibleStrategy;
|
||||||
|
this.isSafeCall = JetPsiUtil.isSafeCall(basicResolutionContext.call);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ResolutionCandidate<D>> setIsSafeCall(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||||
|
for (ResolutionCandidate<D> candidate : candidates) {
|
||||||
|
candidate.setSafeCall(isSafeCall);
|
||||||
|
}
|
||||||
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
public void addLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||||
if (!candidates.isEmpty()) {
|
if (!candidates.isEmpty()) {
|
||||||
localExtensions.add(candidates);
|
localExtensions.add(setIsSafeCall(candidates));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMembers(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
public void addMembers(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||||
if (!candidates.isEmpty()) {
|
if (!candidates.isEmpty()) {
|
||||||
members.add(candidates);
|
members.add(setIsSafeCall(candidates));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNonLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
public void addNonLocalExtensions(@NotNull Collection<ResolutionCandidate<D>> candidates) {
|
||||||
if (!candidates.isEmpty()) {
|
if (!candidates.isEmpty()) {
|
||||||
nonLocalExtensions.add(candidates);
|
nonLocalExtensions.add(setIsSafeCall(candidates));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResolutionTask<D>> getTasks() {
|
public List<ResolutionTask<D, F>> getTasks() {
|
||||||
if (tasks == null) {
|
if (tasks == null) {
|
||||||
tasks = Lists.newArrayList();
|
tasks = Lists.newArrayList();
|
||||||
List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList();
|
List<Collection<ResolutionCandidate<D>>> candidateList = Lists.newArrayList();
|
||||||
@@ -89,7 +101,7 @@ public class ResolutionTaskHolder<D extends CallableDescriptor> {
|
|||||||
for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
|
for (Collection<ResolutionCandidate<D>> candidates : candidateList) {
|
||||||
Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy);
|
Collection<ResolutionCandidate<D>> filteredCandidates = Collections2.filter(candidates, visibilityStrategy);
|
||||||
if (!filteredCandidates.isEmpty()) {
|
if (!filteredCandidates.isEmpty()) {
|
||||||
tasks.add(new ResolutionTask<D>(filteredCandidates, reference, basicResolutionContext));
|
tasks.add(new ResolutionTask<D, F>(filteredCandidates, reference, basicResolutionContext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ public interface ResolvedCall<D extends CallableDescriptor> {
|
|||||||
@NotNull
|
@NotNull
|
||||||
ReceiverDescriptor getThisObject();
|
ReceiverDescriptor getThisObject();
|
||||||
|
|
||||||
|
/** Determines whether receiver argument or this object is substituted for explicit receiver */
|
||||||
|
@NotNull
|
||||||
|
ExplicitReceiverKind getExplicitReceiverKind();
|
||||||
|
|
||||||
/** Values (arguments) for value parameters */
|
/** Values (arguments) for value parameters */
|
||||||
@NotNull
|
@NotNull
|
||||||
Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments();
|
Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments();
|
||||||
@@ -57,4 +61,6 @@ public interface ResolvedCall<D extends CallableDescriptor> {
|
|||||||
/** What's substituted for type parameters */
|
/** What's substituted for type parameters */
|
||||||
@NotNull
|
@NotNull
|
||||||
Map<TypeParameterDescriptor, JetType> getTypeArguments();
|
Map<TypeParameterDescriptor, JetType> getTypeArguments();
|
||||||
|
|
||||||
|
boolean isSafeCall();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.lang.resolve.calls;
|
package org.jetbrains.jet.lang.resolve.calls;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -28,7 +27,6 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -37,31 +35,33 @@ import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.UNKNOWN_STAT
|
|||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedCall<D> {
|
public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedCallWithTrace<D> {
|
||||||
|
|
||||||
public static final Function<ResolvedCallImpl<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_CANDIDATE = new Function<ResolvedCallImpl<? extends CallableDescriptor>, CallableDescriptor>() {
|
public static final Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_CANDIDATE = new Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public CallableDescriptor fun(ResolvedCallImpl<? extends CallableDescriptor> resolvedCall) {
|
public CallableDescriptor fun(ResolvedCallWithTrace<? extends CallableDescriptor> resolvedCall) {
|
||||||
return resolvedCall.getCandidateDescriptor();
|
return resolvedCall.getCandidateDescriptor();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final Function<ResolvedCallImpl<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_RESULT = new Function<ResolvedCallImpl<? extends CallableDescriptor>, CallableDescriptor>() {
|
public static final Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor> MAP_TO_RESULT = new Function<ResolvedCallWithTrace<? extends CallableDescriptor>, CallableDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public CallableDescriptor fun(ResolvedCallImpl<? extends CallableDescriptor> resolvedCall) {
|
public CallableDescriptor fun(ResolvedCallWithTrace<? extends CallableDescriptor> resolvedCall) {
|
||||||
return resolvedCall.getResultingDescriptor();
|
return resolvedCall.getResultingDescriptor();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull ResolutionCandidate<D> candidate) {
|
public static <D extends CallableDescriptor> ResolvedCallImpl<D> create(@NotNull ResolutionCandidate<D> candidate, @NotNull TemporaryBindingTrace trace) {
|
||||||
return new ResolvedCallImpl<D>(candidate.getDescriptor(), candidate.getThisObject(), candidate.getReceiverArgument());
|
return new ResolvedCallImpl<D>(candidate, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final D candidateDescriptor;
|
private final D candidateDescriptor;
|
||||||
private D resultingDescriptor; // Probably substituted
|
private D resultingDescriptor; // Probably substituted
|
||||||
private final ReceiverDescriptor thisObject; // receiver object of a method
|
private final ReceiverDescriptor thisObject; // receiver object of a method
|
||||||
private final ReceiverDescriptor receiverArgument; // receiver of an extension function
|
private final ReceiverDescriptor receiverArgument; // receiver of an extension function
|
||||||
|
private final ExplicitReceiverKind explicitReceiverKind;
|
||||||
|
private final boolean isSafeCall;
|
||||||
|
|
||||||
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
||||||
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
|
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
|
||||||
@@ -70,12 +70,16 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
private TemporaryBindingTrace trace;
|
private TemporaryBindingTrace trace;
|
||||||
private ResolutionStatus status = UNKNOWN_STATUS;
|
private ResolutionStatus status = UNKNOWN_STATUS;
|
||||||
|
|
||||||
private ResolvedCallImpl(@NotNull D candidateDescriptor, @NotNull ReceiverDescriptor thisObject, @NotNull ReceiverDescriptor receiverArgument) {
|
private ResolvedCallImpl(@NotNull ResolutionCandidate<D> candidate, @NotNull TemporaryBindingTrace trace) {
|
||||||
this.candidateDescriptor = candidateDescriptor;
|
this.candidateDescriptor = candidate.getDescriptor();
|
||||||
this.thisObject = thisObject;
|
this.thisObject = candidate.getThisObject();
|
||||||
this.receiverArgument = receiverArgument;
|
this.receiverArgument = candidate.getReceiverArgument();
|
||||||
|
this.explicitReceiverKind = candidate.getExplicitReceiverKind();
|
||||||
|
this.isSafeCall = candidate.isSafeCall();
|
||||||
|
this.trace = trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public ResolutionStatus getStatus() {
|
public ResolutionStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
@@ -85,15 +89,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
this.status = this.status.combine(status);
|
this.status = this.status.combine(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public TemporaryBindingTrace getTrace() {
|
public TemporaryBindingTrace getTrace() {
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTrace(@NotNull TemporaryBindingTrace trace) {
|
|
||||||
this.trace = trace;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public D getCandidateDescriptor() {
|
public D getCandidateDescriptor() {
|
||||||
@@ -138,6 +139,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
return thisObject;
|
return thisObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public ExplicitReceiverKind getExplicitReceiverKind() {
|
||||||
|
return explicitReceiverKind;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
|
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
|
||||||
@@ -171,6 +178,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
this.someArgumentHasNoType = true;
|
this.someArgumentHasNoType = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
return someArgumentHasNoType;
|
return someArgumentHasNoType;
|
||||||
}
|
}
|
||||||
@@ -180,4 +188,9 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
public Map<TypeParameterDescriptor, JetType> getTypeArguments() {
|
public Map<TypeParameterDescriptor, JetType> getTypeArguments() {
|
||||||
return typeArguments;
|
return typeArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSafeCall() {
|
||||||
|
return isSafeCall;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.resolve.TemporaryBindingTrace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author svtk
|
||||||
|
*/
|
||||||
|
public interface ResolvedCallWithTrace<D extends CallableDescriptor> extends ResolvedCall<D> {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
ResolutionStatus getStatus();
|
||||||
|
|
||||||
|
boolean isDirty();
|
||||||
|
|
||||||
|
TemporaryBindingTrace getTrace();
|
||||||
|
}
|
||||||
@@ -74,8 +74,8 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static <D extends CallableDescriptor> List<ResolutionTask<D>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name,
|
public static <D extends CallableDescriptor, F extends D> List<ResolutionTask<D, F>> computePrioritizedTasks(@NotNull BasicResolutionContext context, @NotNull String name,
|
||||||
@NotNull JetReferenceExpression functionReference, @NotNull List<MemberPrioritizer<D>> memberPrioritizers) {
|
@NotNull JetReferenceExpression functionReference, @NotNull List<CallableDescriptorCollector<? extends D>> callableDescriptorCollectors) {
|
||||||
ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver();
|
ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver();
|
||||||
final JetScope scope;
|
final JetScope scope;
|
||||||
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
||||||
@@ -96,23 +96,27 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ResolutionTaskHolder<D> result = new ResolutionTaskHolder<D>(functionReference, context, visibleStrategy );
|
ResolutionTaskHolder<D, F> result = new ResolutionTaskHolder<D, F>(functionReference, context, visibleStrategy);
|
||||||
doComputeTasks(scope, explicitReceiver, name, result, context, memberPrioritizers);
|
for (CallableDescriptorCollector<? extends D> callableDescriptorCollector : callableDescriptorCollectors) {
|
||||||
|
doComputeTasks(scope, explicitReceiver, name, result, context, callableDescriptorCollector);
|
||||||
|
}
|
||||||
return result.getTasks();
|
return result.getTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void doComputeTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver,
|
private static <D extends CallableDescriptor, F extends D> void doComputeTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver,
|
||||||
@NotNull String name, @NotNull ResolutionTaskHolder<D> result,
|
@NotNull String name, @NotNull ResolutionTaskHolder<D, F> result,
|
||||||
@NotNull BasicResolutionContext context, @NotNull List<MemberPrioritizer<D>> memberPrioritizers) {
|
@NotNull BasicResolutionContext context, @NotNull CallableDescriptorCollector<? extends D> callableDescriptorCollector) {
|
||||||
MemberPrioritizer<D> memberPrioritizer = memberPrioritizers.get(0);
|
|
||||||
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext());
|
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext());
|
||||||
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
||||||
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
||||||
|
boolean hasExplicitThisObject = context.call.getThisObject().exists();
|
||||||
|
if (hasExplicitThisObject) {
|
||||||
|
implicitReceivers.add(context.call.getThisObject());
|
||||||
|
}
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
|
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
|
||||||
|
|
||||||
Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, memberPrioritizer.getExtensionsByName(scope, name));
|
Collection<ResolutionCandidate<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, callableDescriptorCollector.getNonMembersByName(scope, name));
|
||||||
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
|
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
|
||||||
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
|
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
|
||||||
//noinspection unchecked,RedundantTypeArguments
|
//noinspection unchecked,RedundantTypeArguments
|
||||||
@@ -120,23 +124,25 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
|
|
||||||
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> members = Lists.newArrayList();
|
||||||
for (ReceiverDescriptor variant : variantsForExplicitReceiver) {
|
for (ReceiverDescriptor variant : variantsForExplicitReceiver) {
|
||||||
Collection<D> membersForThisVariant = memberPrioritizer.getMembersByName(variant.getType(), name);
|
Collection<? extends D> membersForThisVariant = callableDescriptorCollector.getMembersByName(variant.getType(), name);
|
||||||
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members);
|
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members, hasExplicitThisObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.addLocalExtensions(locals);
|
result.addLocalExtensions(locals);
|
||||||
result.addMembers(members);
|
result.addMembers(members);
|
||||||
|
|
||||||
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
||||||
Collection<D> memberExtensions = memberPrioritizer.getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
|
Collection<? extends D> memberExtensions = callableDescriptorCollector.getNonMembersByName(
|
||||||
|
implicitReceiver.getType().getMemberScope(), name);
|
||||||
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
|
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
|
||||||
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver));
|
result.addNonLocalExtensions(convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver, hasExplicitThisObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
result.addNonLocalExtensions(nonlocals);
|
result.addNonLocalExtensions(nonlocals);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Collection<ResolutionCandidate<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), memberPrioritizer.getNonExtensionsByName(scope, name));
|
Collection<ResolutionCandidate<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), callableDescriptorCollector
|
||||||
|
.getNonExtensionsByName(scope, name));
|
||||||
|
|
||||||
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
|
List<ResolutionCandidate<D>> nonlocals = Lists.newArrayList();
|
||||||
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
|
List<ResolutionCandidate<D>> locals = Lists.newArrayList();
|
||||||
@@ -147,25 +153,31 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
result.addNonLocalExtensions(nonlocals);
|
result.addNonLocalExtensions(nonlocals);
|
||||||
|
|
||||||
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
|
||||||
doComputeTasks(scope, implicitReceiver, name, result, context, memberPrioritizers);
|
doComputeTasks(scope, implicitReceiver, name, result, context, callableDescriptorCollector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters) {
|
private static <D extends CallableDescriptor> Collection<ResolutionCandidate<D>> convertWithReceivers(Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects,
|
||||||
|
Iterable<ReceiverDescriptor> receiverParameters, boolean hasExplicitThisObject) {
|
||||||
|
|
||||||
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||||
convertWithReceivers(descriptors, thisObjects, receiverParameters, result);
|
convertWithReceivers(descriptors, thisObjects, receiverParameters, result, hasExplicitThisObject);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void convertWithReceivers(Collection<D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters, Collection<ResolutionCandidate<D>> result) {
|
private static <D extends CallableDescriptor> void convertWithReceivers(Collection<? extends D> descriptors, Iterable<ReceiverDescriptor> thisObjects, Iterable<ReceiverDescriptor> receiverParameters,
|
||||||
|
Collection<ResolutionCandidate<D>> result, boolean hasExplicitThisObject) {
|
||||||
|
|
||||||
for (ReceiverDescriptor thisObject : thisObjects) {
|
for (ReceiverDescriptor thisObject : thisObjects) {
|
||||||
for (ReceiverDescriptor receiverParameter : receiverParameters) {
|
for (ReceiverDescriptor receiverParameter : receiverParameters) {
|
||||||
for (D extension : descriptors) {
|
for (D extension : descriptors) {
|
||||||
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(extension);
|
ResolutionCandidate<D> candidate = ResolutionCandidate.create(extension);
|
||||||
resolvedCall.setThisObject(thisObject);
|
candidate.setThisObject(thisObject);
|
||||||
resolvedCall.setReceiverArgument(receiverParameter);
|
candidate.setReceiverArgument(receiverParameter);
|
||||||
result.add(resolvedCall);
|
candidate.setExplicitReceiverKind(
|
||||||
|
hasExplicitThisObject ? ExplicitReceiverKind.BOTH_RECEIVERS : ExplicitReceiverKind.THIS_OBJECT);
|
||||||
|
result.add(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,10 +187,12 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
Collection<ResolutionCandidate<D>> result = Lists.newArrayList();
|
||||||
for (ReceiverDescriptor receiverParameter : receiverParameters) {
|
for (ReceiverDescriptor receiverParameter : receiverParameters) {
|
||||||
for (D descriptor : descriptors) {
|
for (D descriptor : descriptors) {
|
||||||
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
|
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
|
||||||
resolvedCall.setReceiverArgument(receiverParameter);
|
candidate.setReceiverArgument(receiverParameter);
|
||||||
if (setImpliedThis(scope, resolvedCall)) {
|
candidate.setExplicitReceiverKind(
|
||||||
result.add(resolvedCall);
|
receiverParameter.exists() ? ExplicitReceiverKind.RECEIVER_ARGUMENT : ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
|
||||||
|
if (setImpliedThis(scope, candidate)) {
|
||||||
|
result.add(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,24 +204,25 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
containingDeclaration = containingDeclaration.getContainingDeclaration();
|
containingDeclaration = containingDeclaration.getContainingDeclaration();
|
||||||
}
|
}
|
||||||
if (containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT) {
|
if (containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT) {
|
||||||
ResolutionCandidate<D> resolvedCall = ResolutionCandidate.create(descriptor);
|
ResolutionCandidate<D> candidate = ResolutionCandidate.create(descriptor);
|
||||||
resolvedCall.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration));
|
candidate.setThisObject(new ClassReceiver((ClassDescriptor) containingDeclaration));
|
||||||
result.add(resolvedCall);
|
candidate.setExplicitReceiverKind(ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
|
||||||
|
result.add(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate<D> resolvedCall) {
|
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolutionCandidate<D> candidate) {
|
||||||
ReceiverDescriptor expectedThisObject = resolvedCall.getDescriptor().getExpectedThisObject();
|
ReceiverDescriptor expectedThisObject = candidate.getDescriptor().getExpectedThisObject();
|
||||||
if (!expectedThisObject.exists()) return true;
|
if (!expectedThisObject.exists()) return true;
|
||||||
List<ReceiverDescriptor> receivers = Lists.newArrayList();
|
List<ReceiverDescriptor> receivers = Lists.newArrayList();
|
||||||
scope.getImplicitReceiversHierarchy(receivers);
|
scope.getImplicitReceiversHierarchy(receivers);
|
||||||
for (ReceiverDescriptor receiver : receivers) {
|
for (ReceiverDescriptor receiver : receivers) {
|
||||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
|
if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
|
||||||
// TODO : Autocasts & nullability
|
// TODO : Autocasts & nullability
|
||||||
resolvedCall.setThisObject(expectedThisObject);
|
candidate.setThisObject(expectedThisObject);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,14 +34,15 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
/*package*/ interface TracingStrategy {
|
/*package*/ interface TracingStrategy {
|
||||||
TracingStrategy EMPTY = new TracingStrategy() {
|
TracingStrategy EMPTY = new TracingStrategy() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {}
|
public <D extends CallableDescriptor> void bindResolvedCall(@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unresolvedReference(@NotNull BindingTrace trace) {}
|
public void unresolvedReference(@NotNull BindingTrace trace) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates) {}
|
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallWithTrace<D>> candidates) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
|
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
|
||||||
@@ -59,10 +60,10 @@ import java.util.List;
|
|||||||
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {}
|
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {}
|
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {}
|
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {}
|
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {}
|
||||||
@@ -71,7 +72,7 @@ import java.util.List;
|
|||||||
public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) {}
|
public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
|
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
|
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
|
||||||
@@ -83,11 +84,11 @@ import java.util.List;
|
|||||||
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor) {}
|
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall);
|
<D extends CallableDescriptor> void bindResolvedCall(@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall);
|
||||||
|
|
||||||
void unresolvedReference(@NotNull BindingTrace trace);
|
void unresolvedReference(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallImpl<D>> candidates);
|
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<ResolvedCallWithTrace<D>> candidates);
|
||||||
|
|
||||||
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
|
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
|
||||||
|
|
||||||
@@ -99,15 +100,15 @@ import java.util.List;
|
|||||||
|
|
||||||
void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount);
|
void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount);
|
||||||
|
|
||||||
<D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors);
|
<D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors);
|
||||||
|
|
||||||
<D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors);
|
<D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallWithTrace<D>> descriptors);
|
||||||
|
|
||||||
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
|
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status);
|
void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status);
|
||||||
|
|
||||||
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
|
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type, boolean isCallForImplicitInvoke);
|
||||||
|
|
||||||
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
|
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
|
||||||
|
|
||||||
|
|||||||
+1
-32
@@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -80,9 +79,7 @@ import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMap
|
|||||||
|
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
D base = getDescriptorForValueArgumentsResolving(candidate);
|
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
||||||
|
|
||||||
List<ValueParameterDescriptor> valueParameters = base.getValueParameters();
|
|
||||||
|
|
||||||
Map<String, ValueParameterDescriptor> parameterByName = Maps.newHashMap();
|
Map<String, ValueParameterDescriptor> parameterByName = Maps.newHashMap();
|
||||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||||
@@ -242,32 +239,4 @@ import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMap
|
|||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Descriptor used to resolve parameter names and default parameter values.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
private static <D extends CallableDescriptor> D getDescriptorForValueArgumentsResolving(D descriptor) {
|
|
||||||
Set<D> allBases = new HashSet<D>();
|
|
||||||
getAllDescriptorsForValueArgumentsResolving(descriptor, allBases);
|
|
||||||
|
|
||||||
if (allBases.size() == 1) {
|
|
||||||
return allBases.iterator().next();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO remove parameter names and parameter default values
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void getAllDescriptorsForValueArgumentsResolving(D descriptor, Set<D> dest) {
|
|
||||||
if (descriptor.getOverriddenDescriptors().isEmpty()) {
|
|
||||||
dest.add(descriptor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (CallableDescriptor overriden : descriptor.getOverriddenDescriptors()) {
|
|
||||||
getAllDescriptorsForValueArgumentsResolving((D) overriden, dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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.FunctionDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author svtk
|
||||||
|
*/
|
||||||
|
public class VariableAsFunctionResolvedCall implements ResolvedCallWithTrace<FunctionDescriptor> {
|
||||||
|
private final ResolvedCallWithTrace<FunctionDescriptor> functionCall;
|
||||||
|
private final ResolvedCallWithTrace<VariableDescriptor> variableCall;
|
||||||
|
|
||||||
|
public VariableAsFunctionResolvedCall(@NotNull ResolvedCallWithTrace<FunctionDescriptor> functionCall,
|
||||||
|
@NotNull ResolvedCallWithTrace<VariableDescriptor> variableCall) {
|
||||||
|
this.functionCall = functionCall;
|
||||||
|
this.variableCall = variableCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResolvedCallWithTrace<FunctionDescriptor> getFunctionCall() {
|
||||||
|
return functionCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResolvedCallWithTrace<VariableDescriptor> getVariableCall() {
|
||||||
|
return variableCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public FunctionDescriptor getCandidateDescriptor() {
|
||||||
|
return functionCall.getResultingDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public FunctionDescriptor getResultingDescriptor() {
|
||||||
|
return functionCall.getResultingDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getReceiverArgument() {
|
||||||
|
return variableCall.getReceiverArgument();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ReceiverDescriptor getThisObject() {
|
||||||
|
return variableCall.getThisObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ExplicitReceiverKind getExplicitReceiverKind() {
|
||||||
|
return variableCall.getExplicitReceiverKind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
|
||||||
|
return functionCall.getValueArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<ResolvedValueArgument> getValueArgumentsByIndex() {
|
||||||
|
return functionCall.getValueArgumentsByIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Map<TypeParameterDescriptor, JetType> getTypeArguments() {
|
||||||
|
return functionCall.getTypeArguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ResolutionStatus getStatus() {
|
||||||
|
if (variableCall.getStatus() == ResolutionStatus.SUCCESS) {
|
||||||
|
return functionCall.getStatus();
|
||||||
|
}
|
||||||
|
return variableCall.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDirty() {
|
||||||
|
return functionCall.isDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemporaryBindingTrace getTrace() {
|
||||||
|
//functionCall.trace is temporary trace above variableCall.trace and is committed already
|
||||||
|
return variableCall.getTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSafeCall() {
|
||||||
|
return variableCall.isSafeCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -239,7 +239,8 @@ public class ErrorUtils {
|
|||||||
public static boolean isErrorType(@NotNull JetType type) {
|
public static boolean isErrorType(@NotNull JetType type) {
|
||||||
return type != TypeUtils.NO_EXPECTED_TYPE && !(type instanceof NamespaceType) &&
|
return type != TypeUtils.NO_EXPECTED_TYPE && !(type instanceof NamespaceType) &&
|
||||||
(
|
(
|
||||||
(type instanceof DeferredType && ((DeferredType) type).getActualType() == null) ||
|
(type instanceof DeferredType && (((DeferredType) type).getActualType() == null
|
||||||
|
|| isErrorType(((DeferredType) type).getActualType()))) ||
|
||||||
type instanceof ErrorTypeImpl ||
|
type instanceof ErrorTypeImpl ||
|
||||||
isError(type.getConstructor())
|
isError(type.getConstructor())
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* 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.types;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
|
import org.jetbrains.jet.util.CommonSuppliers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class SubstitutionUtils {
|
||||||
|
@NotNull
|
||||||
|
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull JetType context) {
|
||||||
|
return buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a context with all the supertypes' parameters substituted
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static TypeSubstitutor buildDeepSubstitutor(@NotNull JetType type) {
|
||||||
|
Map<TypeConstructor, TypeProjection> substitution = Maps.newHashMap();
|
||||||
|
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitution);
|
||||||
|
// we use the mutability of the map here
|
||||||
|
fillInDeepSubstitutor(type, typeSubstitutor, substitution, null);
|
||||||
|
return typeSubstitutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Multimap<TypeConstructor, TypeProjection> buildDeepSubstitutionMultimap(@NotNull JetType type) {
|
||||||
|
Multimap<TypeConstructor, TypeProjection> fullSubstitution = CommonSuppliers.newLinkedHashSetHashSetMultimap();
|
||||||
|
Map<TypeConstructor, TypeProjection> substitution = Maps.newHashMap();
|
||||||
|
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitution);
|
||||||
|
// we use the mutability of the map here
|
||||||
|
fillInDeepSubstitutor(type, typeSubstitutor, substitution, fullSubstitution);
|
||||||
|
return fullSubstitution;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we use the mutability of the substitution map here
|
||||||
|
private static void fillInDeepSubstitutor(@NotNull JetType context, @NotNull TypeSubstitutor substitutor, @NotNull Map<TypeConstructor, TypeProjection> substitution, @Nullable Multimap<TypeConstructor, TypeProjection> fullSubstitution) {
|
||||||
|
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
|
||||||
|
List<TypeProjection> arguments = context.getArguments();
|
||||||
|
|
||||||
|
if (parameters.size() != arguments.size()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < arguments.size(); i++) {
|
||||||
|
TypeProjection argument = arguments.get(i);
|
||||||
|
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||||
|
|
||||||
|
JetType substitute = substitutor.substitute(argument.getType(), Variance.INVARIANT);
|
||||||
|
assert substitute != null;
|
||||||
|
TypeProjection substitutedTypeProjection = new TypeProjection(argument.getProjectionKind(), substitute);
|
||||||
|
substitution.put(typeParameterDescriptor.getTypeConstructor(), substitutedTypeProjection);
|
||||||
|
if (fullSubstitution != null) {
|
||||||
|
fullSubstitution.put(typeParameterDescriptor.getTypeConstructor(), substitutedTypeProjection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (JetStandardClasses.isNothingOrNullableNothing(context)) return;
|
||||||
|
for (JetType supertype : context.getConstructor().getSupertypes()) {
|
||||||
|
fillInDeepSubstitutor(supertype, substitutor, substitution, fullSubstitution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull List<TypeParameterDescriptor> parameters, @NotNull List<TypeProjection> contextArguments) {
|
||||||
|
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
|
||||||
|
fillInSubstitutionContext(parameters, contextArguments, parameterValues);
|
||||||
|
return parameterValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void fillInSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments, Map<TypeConstructor, TypeProjection> parameterValues) {
|
||||||
|
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||||
|
TypeParameterDescriptor parameter = parameters.get(i);
|
||||||
|
TypeProjection value = contextArguments.get(i);
|
||||||
|
parameterValues.put(parameter.getTypeConstructor(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
|
||||||
|
return new TypeProjection(Variance.OUT_VARIANCE, parameterDescriptor.getUpperBoundsAsType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasUnsubstitutedTypeParameters(JetType type) {
|
||||||
|
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(TypeProjection proj : type.getArguments()) {
|
||||||
|
if(hasUnsubstitutedTypeParameters(proj.getType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void assertNotImmediatelyRecursive(Map<TypeConstructor, TypeProjection> context) {
|
||||||
|
// Make sure we never replace a T with "Foo<T>" or something similar,
|
||||||
|
// because the substitution will not terminate in this case
|
||||||
|
// This check is not complete. It does not find cases like
|
||||||
|
// T -> Foo<T1>
|
||||||
|
// T -> Bar<T>
|
||||||
|
|
||||||
|
for (Map.Entry<TypeConstructor, TypeProjection> entry : context.entrySet()) {
|
||||||
|
TypeConstructor key = entry.getKey();
|
||||||
|
TypeProjection value = entry.getValue();
|
||||||
|
if (TypeUtils.typeConstructorUsedInType(key, value.getType())) {
|
||||||
|
throw new IllegalStateException("Immediately recursive substitution: " + context + "\nProblematic parameter: " + key + " -> " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -127,7 +127,7 @@ public class TypeSubstitutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static TypeSubstitutor create(@NotNull JetType context) {
|
public static TypeSubstitutor create(@NotNull JetType context) {
|
||||||
return create(TypeUtils.buildSubstitutionContext(context));
|
return create(SubstitutionUtils.buildSubstitutionContext(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -254,7 +254,7 @@ public class TypeSubstitutor {
|
|||||||
assert typeToSubstituteIn.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
assert typeToSubstituteIn.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
||||||
|
|
||||||
if (!allows(parameterVariance, passedProjectionKind)) {
|
if (!allows(parameterVariance, passedProjectionKind)) {
|
||||||
return TypeUtils.makeStarProjection(correspondingTypeParameter);
|
return SubstitutionUtils.makeStarProjection(correspondingTypeParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return substitutionResult(correspondingTypeParameter, effectiveContextVariance, passedProjectionKind, projectionValue, recursionDepth + 1);
|
return substitutionResult(correspondingTypeParameter, effectiveContextVariance, passedProjectionKind, projectionValue, recursionDepth + 1);
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.types;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.util.Processor;
|
import com.intellij.util.Processor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -36,7 +35,6 @@ import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.util.CommonSuppliers;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -140,7 +138,9 @@ public class TypeUtils {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
|
public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
|
||||||
assert !types.isEmpty();
|
if (types.isEmpty()) {
|
||||||
|
return JetStandardClasses.getNullableAnyType();
|
||||||
|
}
|
||||||
|
|
||||||
if (types.size() == 1) {
|
if (types.size() == 1) {
|
||||||
return types.iterator().next();
|
return types.iterator().next();
|
||||||
@@ -399,80 +399,6 @@ public class TypeUtils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull JetType context) {
|
|
||||||
return buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a context with all the supertypes' parameters substituted
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public static TypeSubstitutor buildDeepSubstitutor(@NotNull JetType type) {
|
|
||||||
Map<TypeConstructor, TypeProjection> substitution = Maps.newHashMap();
|
|
||||||
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitution);
|
|
||||||
// we use the mutability of the map here
|
|
||||||
fillInDeepSubstitutor(type, typeSubstitutor, substitution, null);
|
|
||||||
return typeSubstitutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Multimap<TypeConstructor, TypeProjection> buildDeepSubstitutionMultimap(@NotNull JetType type) {
|
|
||||||
Multimap<TypeConstructor, TypeProjection> fullSubstitution = CommonSuppliers.newLinkedHashSetHashSetMultimap();
|
|
||||||
Map<TypeConstructor, TypeProjection> substitution = Maps.newHashMap();
|
|
||||||
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitution);
|
|
||||||
// we use the mutability of the map here
|
|
||||||
fillInDeepSubstitutor(type, typeSubstitutor, substitution, fullSubstitution);
|
|
||||||
return fullSubstitution;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we use the mutability of the substitution map here
|
|
||||||
private static void fillInDeepSubstitutor(@NotNull JetType context, @NotNull TypeSubstitutor substitutor, @NotNull Map<TypeConstructor, TypeProjection> substitution, @Nullable Multimap<TypeConstructor, TypeProjection> fullSubstitution) {
|
|
||||||
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
|
|
||||||
List<TypeProjection> arguments = context.getArguments();
|
|
||||||
|
|
||||||
if (parameters.size() != arguments.size()) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < arguments.size(); i++) {
|
|
||||||
TypeProjection argument = arguments.get(i);
|
|
||||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
|
||||||
|
|
||||||
JetType substitute = substitutor.substitute(argument.getType(), Variance.INVARIANT);
|
|
||||||
assert substitute != null;
|
|
||||||
TypeProjection substitutedTypeProjection = new TypeProjection(argument.getProjectionKind(), substitute);
|
|
||||||
substitution.put(typeParameterDescriptor.getTypeConstructor(), substitutedTypeProjection);
|
|
||||||
if (fullSubstitution != null) {
|
|
||||||
fullSubstitution.put(typeParameterDescriptor.getTypeConstructor(), substitutedTypeProjection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (JetStandardClasses.isNothingOrNullableNothing(context)) return;
|
|
||||||
for (JetType supertype : context.getConstructor().getSupertypes()) {
|
|
||||||
fillInDeepSubstitutor(supertype, substitutor, substitution, fullSubstitution);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull List<TypeParameterDescriptor> parameters, @NotNull List<TypeProjection> contextArguments) {
|
|
||||||
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
|
|
||||||
fillInSubstitutionContext(parameters, contextArguments, parameterValues);
|
|
||||||
return parameterValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void fillInSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments, Map<TypeConstructor, TypeProjection> parameterValues) {
|
|
||||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
|
||||||
TypeParameterDescriptor parameter = parameters.get(i);
|
|
||||||
TypeProjection value = contextArguments.get(i);
|
|
||||||
parameterValues.put(parameter.getTypeConstructor(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
|
|
||||||
return new TypeProjection(Variance.OUT_VARIANCE, parameterDescriptor.getUpperBoundsAsType());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void collectImmediateSupertypes(@NotNull JetType type, @NotNull Collection<JetType> result) {
|
private static void collectImmediateSupertypes(@NotNull JetType type, @NotNull Collection<JetType> result) {
|
||||||
TypeSubstitutor substitutor = TypeSubstitutor.create(type);
|
TypeSubstitutor substitutor = TypeSubstitutor.create(type);
|
||||||
for (JetType supertype : type.getConstructor().getSupertypes()) {
|
for (JetType supertype : type.getConstructor().getSupertypes()) {
|
||||||
@@ -546,21 +472,19 @@ public class TypeUtils {
|
|||||||
return new ArrayList<ClassDescriptor>(classDescriptors);
|
return new ArrayList<ClassDescriptor>(classDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasUnsubstitutedTypeParameters(JetType type) {
|
|
||||||
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(TypeProjection proj : type.getArguments()) {
|
|
||||||
if(hasUnsubstitutedTypeParameters(proj.getType())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean equalTypes(@NotNull JetType a, @NotNull JetType b) {
|
public static boolean equalTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||||
return JetTypeChecker.INSTANCE.isSubtypeOf(a, b) && JetTypeChecker.INSTANCE.isSubtypeOf(b, a);
|
return JetTypeChecker.INSTANCE.isSubtypeOf(a, b) && JetTypeChecker.INSTANCE.isSubtypeOf(b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean typeConstructorUsedInType(@NotNull TypeConstructor key, @NotNull JetType value) {
|
||||||
|
if (value.getConstructor() == key) return true;
|
||||||
|
for (TypeProjection projection : value.getArguments()) {
|
||||||
|
if (typeConstructorUsedInType(key, projection.getType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -285,7 +285,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
{
|
{
|
||||||
Multimap<TypeConstructor, TypeProjection> typeSubstitutionMap =
|
Multimap<TypeConstructor, TypeProjection> typeSubstitutionMap =
|
||||||
TypeUtils.buildDeepSubstitutionMultimap(targetType);
|
SubstitutionUtils.buildDeepSubstitutionMultimap(targetType);
|
||||||
|
|
||||||
for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) {
|
for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) {
|
||||||
TypeProjection actualTypeParameter = actualType.getArguments().get(i);
|
TypeProjection actualTypeParameter = actualType.getArguments().get(i);
|
||||||
@@ -310,7 +310,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
(ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null);
|
(ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null);
|
||||||
|
|
||||||
Multimap<TypeConstructor, TypeProjection> clearTypeSubstitutionMap =
|
Multimap<TypeConstructor, TypeProjection> clearTypeSubstitutionMap =
|
||||||
TypeUtils.buildDeepSubstitutionMultimap(targetTypeClerared);
|
SubstitutionUtils.buildDeepSubstitutionMultimap(targetTypeClerared);
|
||||||
|
|
||||||
Set<JetType> clearSubstituted = new HashSet<JetType>();
|
Set<JetType> clearSubstituted = new HashSet<JetType>();
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "is List<*>"
|
// "is List<*>"
|
||||||
if (typeProjection.equals(TypeUtils.makeStarProjection(typeParameter))) {
|
if (typeProjection.equals(SubstitutionUtils.makeStarProjection(typeParameter))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,6 +472,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
|
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
|
||||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
|
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
|
||||||
|
if (superTypeQualifier != null) {
|
||||||
|
context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, context.scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, context);
|
return DataFlowUtils.checkType(result, expression, context);
|
||||||
@@ -956,7 +959,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSenselessComparisonWithNull(JetType firstType, JetExpression secondExpression) {
|
private boolean isSenselessComparisonWithNull(@Nullable JetType firstType, @NotNull JetExpression secondExpression) {
|
||||||
|
if (firstType == null) return false;
|
||||||
return !firstType.isNullable() && secondExpression instanceof JetConstantExpression && secondExpression.getNode().getElementType() == JetNodeTypes.NULL;
|
return !firstType.isNullable() && secondExpression instanceof JetConstantExpression && secondExpression.getNode().getElementType() == JetNodeTypes.NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -134,10 +134,10 @@ public class ExpressionTypingUtils {
|
|||||||
|
|
||||||
public static void checkWrappingInRef(JetSimpleNameExpression expression, ExpressionTypingContext context) {
|
public static void checkWrappingInRef(JetSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||||
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(context.trace.getBindingContext(), expression, true);
|
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(context.trace.getBindingContext(), expression, true);
|
||||||
if (variable != null && variable.isVar()) {
|
if (variable != null) {
|
||||||
DeclarationDescriptor containingDeclaration = variable.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = variable.getContainingDeclaration();
|
||||||
if (context.scope.getContainingDeclaration() != containingDeclaration && containingDeclaration instanceof CallableDescriptor) {
|
if (context.scope.getContainingDeclaration() != containingDeclaration && containingDeclaration instanceof CallableDescriptor) {
|
||||||
context.trace.record(MUST_BE_WRAPPED_IN_A_REF, variable);
|
context.trace.record(CAPTURED_IN_CLOSURE, variable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.types.lang;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -25,6 +26,8 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.FqName;
|
import org.jetbrains.jet.lang.resolve.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.*;
|
import org.jetbrains.jet.lang.resolve.scopes.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.JetTypeImpl;
|
import org.jetbrains.jet.lang.types.JetTypeImpl;
|
||||||
@@ -189,16 +192,23 @@ public class JetStandardClasses {
|
|||||||
STANDARD_CLASSES_NAMESPACE,
|
STANDARD_CLASSES_NAMESPACE,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
"Function" + i);
|
"Function" + i);
|
||||||
|
|
||||||
|
SimpleFunctionDescriptorImpl invoke = new SimpleFunctionDescriptorImpl(function, Collections.<AnnotationDescriptor>emptyList(), "invoke", CallableMemberDescriptor.Kind.DECLARATION);
|
||||||
|
WritableScope scopeForInvoke = createScopeForInvokeFunction(function, invoke);
|
||||||
|
List<TypeParameterDescriptor> typeParameters = createTypeParameters(i, function);
|
||||||
FUNCTION[i] = function.initialize(
|
FUNCTION[i] = function.initialize(
|
||||||
false,
|
false,
|
||||||
createTypeParameters(i, function),
|
typeParameters,
|
||||||
Collections.singleton(getAnyType()), STUB, Collections.<ConstructorDescriptor>emptySet(), null);
|
Collections.singleton(getAnyType()), scopeForInvoke, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||||
FUNCTION_TYPE_CONSTRUCTORS.add(FUNCTION[i].getTypeConstructor());
|
FUNCTION_TYPE_CONSTRUCTORS.add(FUNCTION[i].getTypeConstructor());
|
||||||
|
FunctionDescriptorUtil.initializeFromFunctionType(invoke, function.getDefaultType(), new ClassReceiver(FUNCTION[i]), Modality.ABSTRACT, Visibilities.PUBLIC);
|
||||||
|
|
||||||
ClassDescriptorImpl receiverFunction = new ClassDescriptorImpl(
|
ClassDescriptorImpl receiverFunction = new ClassDescriptorImpl(
|
||||||
STANDARD_CLASSES_NAMESPACE,
|
STANDARD_CLASSES_NAMESPACE,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
"ExtensionFunction" + i);
|
"ExtensionFunction" + i);
|
||||||
|
SimpleFunctionDescriptorImpl invokeWithReceiver = new SimpleFunctionDescriptorImpl(receiverFunction, Collections.<AnnotationDescriptor>emptyList(), "invoke", CallableMemberDescriptor.Kind.DECLARATION);
|
||||||
|
WritableScope scopeForInvokeWithReceiver = createScopeForInvokeFunction(receiverFunction, invokeWithReceiver);
|
||||||
List<TypeParameterDescriptor> parameters = createTypeParameters(i, receiverFunction);
|
List<TypeParameterDescriptor> parameters = createTypeParameters(i, receiverFunction);
|
||||||
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound(
|
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound(
|
||||||
receiverFunction,
|
receiverFunction,
|
||||||
@@ -207,11 +217,19 @@ public class JetStandardClasses {
|
|||||||
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
|
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
|
||||||
false,
|
false,
|
||||||
parameters,
|
parameters,
|
||||||
Collections.singleton(getAnyType()), STUB, Collections.<ConstructorDescriptor>emptySet(), null);
|
Collections.singleton(getAnyType()), scopeForInvokeWithReceiver, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||||
RECEIVER_FUNCTION_TYPE_CONSTRUCTORS.add(RECEIVER_FUNCTION[i].getTypeConstructor());
|
RECEIVER_FUNCTION_TYPE_CONSTRUCTORS.add(RECEIVER_FUNCTION[i].getTypeConstructor());
|
||||||
|
FunctionDescriptorUtil.initializeFromFunctionType(invokeWithReceiver, receiverFunction.getDefaultType(), new ClassReceiver(RECEIVER_FUNCTION[i]), Modality.ABSTRACT, Visibilities.PUBLIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static WritableScope createScopeForInvokeFunction(ClassDescriptorImpl function, SimpleFunctionDescriptorImpl invoke) {
|
||||||
|
WritableScope scopeForInvoke = new WritableScopeImpl(STUB, function, RedeclarationHandler.THROW_EXCEPTION).setDebugName("Scope for function type");
|
||||||
|
scopeForInvoke.addFunctionDescriptor(invoke);
|
||||||
|
scopeForInvoke.changeLockLevel(WritableScope.LockLevel.READING);
|
||||||
|
return scopeForInvoke;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<TypeParameterDescriptor> createTypeParameters(int parameterCount, ClassDescriptorImpl function) {
|
private static List<TypeParameterDescriptor> createTypeParameters(int parameterCount, ClassDescriptorImpl function) {
|
||||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
||||||
for (int j = 0; j < parameterCount; j++) {
|
for (int j = 0; j < parameterCount; j++) {
|
||||||
@@ -411,8 +429,9 @@ public class JetStandardClasses {
|
|||||||
}
|
}
|
||||||
arguments.add(defaultProjection(returnType));
|
arguments.add(defaultProjection(returnType));
|
||||||
int size = parameterTypes.size();
|
int size = parameterTypes.size();
|
||||||
TypeConstructor constructor = receiverType == null ? FUNCTION[size].getTypeConstructor() : RECEIVER_FUNCTION[size].getTypeConstructor();
|
ClassDescriptor classDescriptor = receiverType == null ? FUNCTION[size] : RECEIVER_FUNCTION[size];
|
||||||
return new JetTypeImpl(annotations, constructor, false, arguments, STUB);
|
TypeConstructor constructor = classDescriptor.getTypeConstructor();
|
||||||
|
return new JetTypeImpl(annotations, constructor, false, arguments, classDescriptor.getMemberScope(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TypeProjection defaultProjection(JetType returnType) {
|
private static TypeProjection defaultProjection(JetType returnType) {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class JetFileType extends LanguageFileType {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected Icon compute() {
|
protected Icon compute() {
|
||||||
return IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin16x16.png");
|
return IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin_file.png");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,21 +40,25 @@ public class JetFileType extends LanguageFileType {
|
|||||||
super(JetLanguage.INSTANCE);
|
super(JetLanguage.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Kotlin";
|
return "Kotlin";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Kotlin";
|
return "Kotlin";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getDefaultExtension() {
|
public String getDefaultExtension() {
|
||||||
return "kt";
|
return "kt";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Icon getIcon() {
|
public Icon getIcon() {
|
||||||
return myIcon.getValue();
|
return myIcon.getValue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,6 @@
|
|||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="module-library">
|
|
||||||
<library>
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MODULE_DIR$/../../ideaSDK/lib/junit-4.10.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES>
|
|
||||||
<root url="jar://$MODULE_DIR$/../../ideaSDK/lib/junit-4.10-sources.jar!/" />
|
|
||||||
</SOURCES>
|
|
||||||
</library>
|
|
||||||
</orderEntry>
|
|
||||||
<orderEntry type="library" name="idea-full" level="project" />
|
<orderEntry type="library" name="idea-full" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user