Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ done
|
|||||||
test -n "$ideaRoot" || die "Idea root not found"
|
test -n "$ideaRoot" || die "Idea root not found"
|
||||||
|
|
||||||
classpath="$root/out/production/cli"
|
classpath="$root/out/production/cli"
|
||||||
classpath="$classpath:$root/out/production/backend:$root/out/production/frontend:$root/out/production/frontend.java"
|
classpath="$classpath:$root/out/production/backend:$root/out/production/frontend:$root/out/production/frontend.java:$root/out/production/jet.as.java.psi"
|
||||||
classpath="$classpath:$root/out/production/stdlib"
|
classpath="$classpath:$root/out/production/stdlib"
|
||||||
classpath="$classpath:$root/lib/*:$ideaRoot/lib/*:$ideaRoot/lib/rt/*"
|
classpath="$classpath:$root/lib/*:$ideaRoot/lib/*:$ideaRoot/lib/rt/*"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package org.jetbrains.jet.buildtools.ant;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.buildtools.core.Util.*;
|
||||||
|
import org.apache.tools.ant.Task;
|
||||||
|
import org.jetbrains.jet.buildtools.core.BytecodeCompiler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin bytecode compiler Ant task.
|
||||||
|
*
|
||||||
|
* See
|
||||||
|
* http://evgeny-goldin.org/javadoc/ant/tutorial-writing-tasks.html
|
||||||
|
* http://evgeny-goldin.org/javadoc/ant/Tasks/javac.html - attribute names should be similar to {@code <javac>}.
|
||||||
|
*/
|
||||||
|
public class BytecodeCompilerTask extends Task {
|
||||||
|
|
||||||
|
private final BytecodeCompiler compiler = new BytecodeCompiler();
|
||||||
|
|
||||||
|
private File srcdir;
|
||||||
|
private File file;
|
||||||
|
private File destdir;
|
||||||
|
private File destjar;
|
||||||
|
private boolean includeRuntime = true;
|
||||||
|
private boolean excludeStdlib = false;
|
||||||
|
|
||||||
|
public void setSrcdir ( File srcdir ) { this.srcdir = srcdir; }
|
||||||
|
public void setFile ( File file ) { this.file = file; }
|
||||||
|
public void setDestdir ( File destdir ) { this.destdir = destdir; }
|
||||||
|
public void setDestjar ( File destjar ) { this.destjar = destjar; }
|
||||||
|
|
||||||
|
public void setIncludeRuntime ( boolean includeRuntime ) { this.includeRuntime = includeRuntime; }
|
||||||
|
public void setExcludeStdlib ( boolean excludeStdlib ) { this.excludeStdlib = excludeStdlib; }
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
|
||||||
|
if (( this.srcdir != null ) || ( this.file != null )) {
|
||||||
|
|
||||||
|
if (( this.destdir == null ) && ( this.destjar == null )) {
|
||||||
|
throw new RuntimeException( "\"destdir\" or \"destjar\" should be specified" );
|
||||||
|
}
|
||||||
|
|
||||||
|
String src = getPath( this.srcdir != null ? this.srcdir : this.file );
|
||||||
|
String dest = getPath( this.destdir != null ? this.destdir : this.destjar );
|
||||||
|
|
||||||
|
log( String.format( "[%s] => [%s]", src, dest ));
|
||||||
|
|
||||||
|
if ( this.destdir != null ) {
|
||||||
|
compiler.sourcesToDir( src, dest, this.includeRuntime, this.excludeStdlib );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
compiler.sourcesToJar( src, dest, this.includeRuntime, this.excludeStdlib );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException( "Operation is not supported yet" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.jetbrains.jet.buildtools.ant;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.Task;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kotlin JavaScript compiler Ant task.
|
||||||
|
* http://evgeny-goldin.org/javadoc/ant/tutorial-writing-tasks.html
|
||||||
|
*/
|
||||||
|
public class JavaScriptCompilerTask extends Task {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
log( "JavaScriptCompilerTask" );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
||||||
|
<!-- http://evgeny-goldin.org/javadoc/ant/Types/antlib.html -->
|
||||||
|
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
||||||
|
|
||||||
|
<antlib>
|
||||||
|
<taskdef
|
||||||
|
name = "kotlinc"
|
||||||
|
classname = "org.jetbrains.jet.buildtools.ant.BytecodeCompilerTask"/>
|
||||||
|
<taskdef
|
||||||
|
name = "kotlinJSc"
|
||||||
|
classname = "org.jetbrains.jet.buildtools.ant.JavaScriptCompilerTask"/>
|
||||||
|
</antlib>
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
<project name="build-tools" default="buildToolsJar">
|
||||||
|
|
||||||
|
<property name="tests-dir" location="${output}/ant-test/build-tools-test"/>
|
||||||
|
<property name="tests-jar" location="${tests-dir}/out.jar"/>
|
||||||
|
<property name="kotlin-home" location="${output}/ant-test/kotlin-home"/>
|
||||||
|
|
||||||
|
|
||||||
|
<taskdef resource="net/sf/antcontrib/antlib.xml">
|
||||||
|
<classpath>
|
||||||
|
<pathelement location="${basedir}/build-tools/lib/ant-contrib-1.0b3.jar"/>
|
||||||
|
</classpath>
|
||||||
|
</taskdef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Re-creates ${kotlin-home} and defines <kotlin> tasks using "${kotlin-home}/lib" jars -->
|
||||||
|
<macrodef name="setup-kotlin-home">
|
||||||
|
<sequential>
|
||||||
|
|
||||||
|
<if>
|
||||||
|
<not>
|
||||||
|
<available file="${output}/${output.name}.zip"/>
|
||||||
|
</not>
|
||||||
|
<then>
|
||||||
|
<antcall target="dist"/>
|
||||||
|
</then>
|
||||||
|
</if>
|
||||||
|
|
||||||
|
<delete dir = "${kotlin-home}" failonerror="true"/>
|
||||||
|
<mkdir dir = "${kotlin-home}"/>
|
||||||
|
<unzip src = "${output}/${output.name}.zip"
|
||||||
|
dest = "${kotlin-home}"/>
|
||||||
|
<move todir = "${kotlin-home}">
|
||||||
|
<fileset dir = "${kotlin-home}/kotlinc"/>
|
||||||
|
</move>
|
||||||
|
<delete dir = "${kotlin-home}/kotlinc" failonerror="true"/>
|
||||||
|
|
||||||
|
<taskdef resource = "org/jetbrains/jet/buildtools/ant/antlib.xml">
|
||||||
|
<classpath>
|
||||||
|
<fileset dir = "${kotlin-home}/lib" includes = "*.jar"/>
|
||||||
|
</classpath>
|
||||||
|
</taskdef>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Runs <kotlinc> in test directory -->
|
||||||
|
<macrodef name="kotlinc-dir">
|
||||||
|
<attribute name="file" default=""/>
|
||||||
|
<attribute name="srcdir" default=""/>
|
||||||
|
<sequential>
|
||||||
|
|
||||||
|
<delete dir = "${tests-dir}"/>
|
||||||
|
<mkdir dir = "${tests-dir}"/>
|
||||||
|
|
||||||
|
<if>
|
||||||
|
<equals arg1="@{file}" arg2=""/>
|
||||||
|
<then>
|
||||||
|
<kotlinc srcdir = "@{srcdir}" destdir = "${tests-dir}" />
|
||||||
|
</then>
|
||||||
|
<else>
|
||||||
|
<kotlinc file = "@{file}" destdir = "${tests-dir}" />
|
||||||
|
</else>
|
||||||
|
</if>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Runs <kotlinc> with test jar -->
|
||||||
|
<macrodef name="kotlinc-jar">
|
||||||
|
<attribute name="file" default=""/>
|
||||||
|
<attribute name="srcdir" default=""/>
|
||||||
|
<sequential>
|
||||||
|
|
||||||
|
<delete dir = "${tests-dir}"/>
|
||||||
|
<mkdir dir = "${tests-dir}"/>
|
||||||
|
<delete file = "${tests-jar}"/>
|
||||||
|
|
||||||
|
<if>
|
||||||
|
<equals arg1="@{file}" arg2=""/>
|
||||||
|
<then>
|
||||||
|
<kotlinc srcdir = "@{srcdir}" destjar = "${tests-jar}"/>
|
||||||
|
</then>
|
||||||
|
<else>
|
||||||
|
<kotlinc file = "@{file}" destjar = "${tests-jar}"/>
|
||||||
|
</else>
|
||||||
|
</if>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Runs <java> for compiled classes and verifies the output correctness -->
|
||||||
|
<macrodef name="run-java">
|
||||||
|
<attribute name="out"/>
|
||||||
|
<attribute name="classname" default="namespace"/>
|
||||||
|
<attribute name="args" default=""/>
|
||||||
|
<attribute name="equals" default="true"/> <!-- Whether strict equality of output to @{out} required -->
|
||||||
|
<attribute name="run-jar" default="false"/> <!-- Whether to run compiled classes or a jar file -->
|
||||||
|
<sequential>
|
||||||
|
<var name = "java-out" unset = "true"/>
|
||||||
|
|
||||||
|
<if>
|
||||||
|
<istrue value="@{run-jar}"/>
|
||||||
|
<then>
|
||||||
|
<java outputproperty = "java-out"
|
||||||
|
classname = "@{classname}"
|
||||||
|
failonerror = "true">
|
||||||
|
<classpath>
|
||||||
|
<pathelement path = "${tests-jar}"/>
|
||||||
|
</classpath>
|
||||||
|
<arg line = "@{args}"/>
|
||||||
|
</java>
|
||||||
|
</then>
|
||||||
|
<else>
|
||||||
|
<java outputproperty = "java-out"
|
||||||
|
classname = "@{classname}"
|
||||||
|
failonerror = "true">
|
||||||
|
<classpath>
|
||||||
|
<pathelement path = "${tests-dir}"/>
|
||||||
|
<fileset file = "${kotlin-home}/lib/kotlin-runtime.jar"/>
|
||||||
|
</classpath>
|
||||||
|
<arg line = "@{args}"/>
|
||||||
|
</java>
|
||||||
|
</else>
|
||||||
|
</if>
|
||||||
|
|
||||||
|
<if>
|
||||||
|
<or>
|
||||||
|
<equals arg1="${java-out}" arg2="@{out}"/>
|
||||||
|
<and>
|
||||||
|
<isfalse value="@{equals}"/>
|
||||||
|
<contains string="${java-out}" substring="@{out}"/>
|
||||||
|
</and>
|
||||||
|
</or>
|
||||||
|
<then>
|
||||||
|
<echo>${java-out}</echo>
|
||||||
|
</then>
|
||||||
|
<else>
|
||||||
|
<fail message="Test failed: '${java-out}' (received) != '@{out}' (expected), equals = [@{equals}]"/>
|
||||||
|
</else>
|
||||||
|
</if>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Compiles "Hello.kt" as a single file and a folder, runs <java> and verifies the output -->
|
||||||
|
<macrodef name="hello-test">
|
||||||
|
<attribute name="root"/>
|
||||||
|
<attribute name="args" default=""/>
|
||||||
|
<attribute name="out"/>
|
||||||
|
<sequential>
|
||||||
|
<kotlinc-dir file = "@{root}/Hello.kt"/>
|
||||||
|
<run-java args = "@{args}" out = "@{out}"/>
|
||||||
|
<kotlinc-dir srcdir = "@{root}"/>
|
||||||
|
<run-java args = "@{args}" out = "@{out}"/>
|
||||||
|
|
||||||
|
<kotlinc-jar file = "@{root}/Hello.kt"/>
|
||||||
|
<run-java args = "@{args}" out = "@{out}" run-jar="true"/>
|
||||||
|
<kotlinc-jar srcdir = "@{root}"/>
|
||||||
|
<run-java args = "@{args}" out = "@{out}" run-jar="true"/>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Runs all Hello tests -->
|
||||||
|
<macrodef name="hello-tests">
|
||||||
|
<sequential>
|
||||||
|
<hello-test root="${basedir}/build-tools/test/hello/1" out="Hello, world!"/>
|
||||||
|
<hello-test root="${basedir}/build-tools/test/hello/2" args="Kotlin-Developer" out="Hello, Kotlin-Developer!"/>
|
||||||
|
<hello-test root="${basedir}/build-tools/test/hello/3" args="Mickey-Mouse" out="Hello, Mickey-Mouse!"/>
|
||||||
|
<hello-test root="${basedir}/build-tools/test/hello/4" args="IT" out="Ciao!"/>
|
||||||
|
<hello-test root="${basedir}/build-tools/test/hello/4" args="FR" out="Salut!"/>
|
||||||
|
<hello-test root="${basedir}/build-tools/test/hello/5" args="Donald-Duck" out="Hello, Donald-Duck!"/>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Compiles, runs and verifies the output of web demo longer examples -->
|
||||||
|
<macrodef name="longer-examples-tests">
|
||||||
|
<sequential>
|
||||||
|
<kotlinc-dir srcdir = "${basedir}/build-tools/test/longer-examples"/>
|
||||||
|
|
||||||
|
<run-java classname = "bottles.namespace" equals="false" out="12 bottles of beer on the wall, 12 bottles of beer."/>
|
||||||
|
<!--<run-java classname = "maze.namespace" equals="false" out="O ~OOOOOOOOOOOOOO"/>-->
|
||||||
|
<!--<run-java classname = "life.namespace" equals="false" out="*** ** ** ***"/>-->
|
||||||
|
<run-java classname = "html.namespace" equals="false" out="<a href="http://jetbrains.com/kotlin">"/>
|
||||||
|
|
||||||
|
<kotlinc-jar srcdir = "${basedir}/build-tools/test/longer-examples"/>
|
||||||
|
|
||||||
|
<run-java classname = "bottles.namespace" equals="false" run-jar="true" out="12 bottles of beer on the wall, 12 bottles of beer."/>
|
||||||
|
<!--<run-java classname = "maze.namespace" equals="false" run-jar="true" out="O ~OOOOOOOOOOOOOO"/>-->
|
||||||
|
<!--<run-java classname = "life.namespace" equals="false" run-jar="true" out="*** ** ** ***"/>-->
|
||||||
|
<run-java classname = "html.namespace" equals="false" run-jar="true" out="<a href="http://jetbrains.com/kotlin">"/>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Verifies build fails if <kotlinc> fails -->
|
||||||
|
<macrodef name="compilation-fail-test">
|
||||||
|
<sequential>
|
||||||
|
<var name="failed" value="false"/>
|
||||||
|
<trycatch property="error-message" reference="bar">
|
||||||
|
<try>
|
||||||
|
<!-- Should fail -->
|
||||||
|
<kotlinc-dir srcdir = "${basedir}/build-tools/test/compilation-fail"/>
|
||||||
|
</try>
|
||||||
|
<catch>
|
||||||
|
<var name="failed" value="true"/>
|
||||||
|
<echo>ERROR: was expected here</echo>
|
||||||
|
</catch>
|
||||||
|
</trycatch>
|
||||||
|
<if>
|
||||||
|
<isfalse value="${failed}"/>
|
||||||
|
<then>
|
||||||
|
<fail message="kotlinc-dir: compilation should have failed!"/>
|
||||||
|
</then>
|
||||||
|
</if>
|
||||||
|
|
||||||
|
<var name="failed" value="false"/>
|
||||||
|
<trycatch property="error-message" reference="bar">
|
||||||
|
<try>
|
||||||
|
<!-- Should fail -->
|
||||||
|
<kotlinc-jar srcdir = "${basedir}/build-tools/test/compilation-fail"/>
|
||||||
|
</try>
|
||||||
|
<catch>
|
||||||
|
<var name="failed" value="true"/>
|
||||||
|
<echo>ERROR: was expected here</echo>
|
||||||
|
</catch>
|
||||||
|
</trycatch>
|
||||||
|
<if>
|
||||||
|
<isfalse value="${failed}"/>
|
||||||
|
<then>
|
||||||
|
<fail message="kotlinc-jar: compilation should have failed!"/>
|
||||||
|
</then>
|
||||||
|
</if>
|
||||||
|
</sequential>
|
||||||
|
</macrodef>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Creates build tools distribution jar -->
|
||||||
|
<target name="buildToolsJar" depends="compile">
|
||||||
|
<mkdir dir ="${output}/classes/buildTools"/>
|
||||||
|
<javac destdir="${output}/classes/buildTools" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
|
||||||
|
<src>
|
||||||
|
<dirset dir="${basedir}/build-tools">
|
||||||
|
<include name="core/src"/>
|
||||||
|
<include name="ant/src"/>
|
||||||
|
<include name="maven/src"/>
|
||||||
|
<include name="gradle/src"/>
|
||||||
|
</dirset>
|
||||||
|
</src>
|
||||||
|
<compilerarg value="-Xlint:all"/>
|
||||||
|
<classpath>
|
||||||
|
<path refid = "classpath.kotlin"/>
|
||||||
|
<fileset dir = "${idea.sdk}/ant/lib" includes="*.jar"/>
|
||||||
|
</classpath>
|
||||||
|
</javac>
|
||||||
|
<jar destfile="${output}/kotlin-build-tools.jar">
|
||||||
|
<fileset dir = "${output}/classes/buildTools"/>
|
||||||
|
<fileset dir = "${basedir}/build-tools/ant/src" includes="**/*.xml"/>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Tests build tools distribution jar -->
|
||||||
|
<target name="buildToolsTest">
|
||||||
|
<setup-kotlin-home/>
|
||||||
|
<hello-tests/>
|
||||||
|
<longer-examples-tests/>
|
||||||
|
<compilation-fail-test/>
|
||||||
|
</target>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package org.jetbrains.jet.buildtools.core;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.compiler.CompileEnvironment;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for Kotlin bytecode compiler.
|
||||||
|
*/
|
||||||
|
public class BytecodeCompiler {
|
||||||
|
|
||||||
|
private final CompileEnvironment ENV = createCompileEnvironment();
|
||||||
|
|
||||||
|
|
||||||
|
public BytecodeCompiler () {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and initializes new {@link CompileEnvironment} instance.
|
||||||
|
* @return new {@link CompileEnvironment} instance
|
||||||
|
*/
|
||||||
|
private CompileEnvironment createCompileEnvironment () {
|
||||||
|
|
||||||
|
CompileEnvironment environment = new CompileEnvironment();
|
||||||
|
environment.setJavaRuntime( CompileEnvironment.findRtJar( true ));
|
||||||
|
|
||||||
|
if ( ! environment.initializeKotlinRuntime()) {
|
||||||
|
throw new RuntimeException( "No Kotlin runtime library found" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves compilation error message.
|
||||||
|
* @param source compilation source
|
||||||
|
* @return compilation error message
|
||||||
|
*/
|
||||||
|
private String compilationError ( String source ) {
|
||||||
|
return String.format( "[%s] compilation failed, see \"ERROR:\" messages above for more details.", source );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code CompileEnvironment#compileBunchOfSources} wrapper.
|
||||||
|
*
|
||||||
|
* @param source compilation source (directory or file)
|
||||||
|
* @param destination compilation destination
|
||||||
|
*/
|
||||||
|
public void sourcesToDir ( String source, String destination, boolean includeRuntime, boolean excludeStdlib ) {
|
||||||
|
boolean success = ENV.compileBunchOfSources( source, null, destination, includeRuntime, ! excludeStdlib );
|
||||||
|
if ( ! success ) {
|
||||||
|
throw new RuntimeException( compilationError( source ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code CompileEnvironment#compileBunchOfSources} wrapper.
|
||||||
|
*
|
||||||
|
* @param source compilation source (directory or file)
|
||||||
|
* @param jar compilation destination jar
|
||||||
|
*/
|
||||||
|
public void sourcesToJar ( String source, String jar, boolean includeRuntime, boolean excludeStdlib ) {
|
||||||
|
boolean success = ENV.compileBunchOfSources( source, jar, null, includeRuntime, ! excludeStdlib );
|
||||||
|
if ( ! success ) {
|
||||||
|
throw new RuntimeException( compilationError( source ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.jetbrains.jet.buildtools.core;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for Kotlin JavaScript compiler.
|
||||||
|
*/
|
||||||
|
public class JavaScriptCompiler {
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.jetbrains.jet.buildtools.core;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General convenient utilities.
|
||||||
|
*/
|
||||||
|
public final class Util {
|
||||||
|
|
||||||
|
private Util () {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code file.getCanonicalFile().getPath()} convenience wrapper.
|
||||||
|
* @param f file to get its canonical path.
|
||||||
|
* @return file's canonical path
|
||||||
|
*/
|
||||||
|
public static String getPath( File f ) {
|
||||||
|
try {
|
||||||
|
return f.getCanonicalFile().getPath();
|
||||||
|
}
|
||||||
|
catch ( IOException e ) {
|
||||||
|
throw new RuntimeException( String.format( "Failed to resolve canonical file of [%s]: %s", f, e ), e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* "Bottles.kt" that doesn't compile, see line 6.
|
||||||
|
*/
|
||||||
|
package bottles
|
||||||
|
|
||||||
|
fun main(args : Array<String>
|
||||||
|
if (args.isEmpty) {
|
||||||
|
printBottles(99)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
printBottles(Integer.parseInt(args[0]))
|
||||||
|
}
|
||||||
|
catch (e : NumberFormatException) {
|
||||||
|
System.err?.println("You have passed '${args[0]}' as a number of bottles, " +
|
||||||
|
"but it is not a valid integral number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printBottles(bottleCount : Int) {
|
||||||
|
if (bottleCount <= 0) {
|
||||||
|
println("No bottles - no song")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println("The \"${bottlesOfBeer(bottleCount)}\" song\n")
|
||||||
|
|
||||||
|
var bottles = bottleCount
|
||||||
|
while (bottles > 0) {
|
||||||
|
val bottlesOfBeer = bottlesOfBeer(bottles)
|
||||||
|
print("$bottlesOfBeer on the wall, $bottlesOfBeer.\nTake one down, pass it around, ")
|
||||||
|
bottles--
|
||||||
|
println("${bottlesOfBeer(bottles)} on the wall.\n")
|
||||||
|
}
|
||||||
|
println("No more bottles of beer on the wall, no more bottles of beer.\n" +
|
||||||
|
"Go to the store and buy some more, ${bottlesOfBeer(bottleCount)} on the wall.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bottlesOfBeer(count : Int) : String =
|
||||||
|
when (count) {
|
||||||
|
0 -> "no more bottles"
|
||||||
|
1 -> "1 bottle"
|
||||||
|
else -> "$count bottles"
|
||||||
|
} + " of beer"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An excerpt from the Standard Library
|
||||||
|
*/
|
||||||
|
|
||||||
|
// From the std.io package
|
||||||
|
// These are simple functions that wrap standard Java API calls
|
||||||
|
fun print(message : String) { System.out?.print(message) }
|
||||||
|
fun println(message : String) { System.out?.println(message) }
|
||||||
|
|
||||||
|
// From the std package
|
||||||
|
// This is an extension property, i.e. a property that is defined for the
|
||||||
|
// type Array<T>, but does not sit inside the class Array
|
||||||
|
val <T> Array<T>.isEmpty : Boolean get() = size == 0
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun main(args : Array<String>) {
|
||||||
|
System.out?.println("Hello, world!")
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun main(args : Array<String>) {
|
||||||
|
if (args.size == 0) {
|
||||||
|
System.out?.println("Please provide a name as a command-line argument")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
System.out?.println("Hello, ${args[0]}!")
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun main(args : Array<String>) {
|
||||||
|
for (name in args)
|
||||||
|
System.out?.println("Hello, $name!")
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun main(args : Array<String>) {
|
||||||
|
val language = if (args.size == 0) "EN" else args[0]
|
||||||
|
System.out?.println(when (language) {
|
||||||
|
"EN" -> "Hello!"
|
||||||
|
"FR" -> "Salut!"
|
||||||
|
"IT" -> "Ciao!"
|
||||||
|
else -> "Sorry, I can't greet you in $language yet"
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class Greeter(val name : String) {
|
||||||
|
fun greet() {
|
||||||
|
System.out?.println("Hello, ${name}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
Greeter(args[0]).greet()
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* This example implements the famous "99 Bottles of Beer" program
|
||||||
|
* See http://99-bottles-of-beer.net/
|
||||||
|
*
|
||||||
|
* The point is to print out a song with the following lyrics:
|
||||||
|
*
|
||||||
|
* The "99 bottles of beer" song
|
||||||
|
*
|
||||||
|
* 99 bottles of beer on the wall, 99 bottles of beer.
|
||||||
|
* Take one down, pass it around, 98 bottles of beer on the wall.
|
||||||
|
*
|
||||||
|
* 98 bottles of beer on the wall, 98 bottles of beer.
|
||||||
|
* Take one down, pass it around, 97 bottles of beer on the wall.
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* 2 bottles of beer on the wall, 2 bottles of beer.
|
||||||
|
* Take one down, pass it around, 1 bottle of beer on the wall.
|
||||||
|
*
|
||||||
|
* 1 bottle of beer on the wall, 1 bottle of beer.
|
||||||
|
* Take one down, pass it around, no more bottles of beer on the wall.
|
||||||
|
*
|
||||||
|
* No more bottles of beer on the wall, no more bottles of beer.
|
||||||
|
* Go to the store and buy some more, 99 bottles of beer on the wall.
|
||||||
|
*
|
||||||
|
* Additionally, you can pass the desired initial number of bottles to use (rather than 99)
|
||||||
|
* as a command-line argument
|
||||||
|
*/
|
||||||
|
package bottles
|
||||||
|
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
if (args.isEmpty) {
|
||||||
|
printBottles(99)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
printBottles(Integer.parseInt(args[0]))
|
||||||
|
}
|
||||||
|
catch (e : NumberFormatException) {
|
||||||
|
System.err?.println("You have passed '${args[0]}' as a number of bottles, " +
|
||||||
|
"but it is not a valid integral number")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printBottles(bottleCount : Int) {
|
||||||
|
if (bottleCount <= 0) {
|
||||||
|
println("No bottles - no song")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println("The \"${bottlesOfBeer(bottleCount)}\" song\n")
|
||||||
|
|
||||||
|
var bottles = bottleCount
|
||||||
|
while (bottles > 0) {
|
||||||
|
val bottlesOfBeer = bottlesOfBeer(bottles)
|
||||||
|
print("$bottlesOfBeer on the wall, $bottlesOfBeer.\nTake one down, pass it around, ")
|
||||||
|
bottles--
|
||||||
|
println("${bottlesOfBeer(bottles)} on the wall.\n")
|
||||||
|
}
|
||||||
|
println("No more bottles of beer on the wall, no more bottles of beer.\n" +
|
||||||
|
"Go to the store and buy some more, ${bottlesOfBeer(bottleCount)} on the wall.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bottlesOfBeer(count : Int) : String =
|
||||||
|
when (count) {
|
||||||
|
0 -> "no more bottles"
|
||||||
|
1 -> "1 bottle"
|
||||||
|
else -> "$count bottles"
|
||||||
|
} + " of beer"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An excerpt from the Standard Library
|
||||||
|
*/
|
||||||
|
|
||||||
|
// From the std.io package
|
||||||
|
// These are simple functions that wrap standard Java API calls
|
||||||
|
fun print(message : String) { System.out?.print(message) }
|
||||||
|
fun println(message : String) { System.out?.println(message) }
|
||||||
|
|
||||||
|
// From the std package
|
||||||
|
// This is an extension property, i.e. a property that is defined for the
|
||||||
|
// type Array<T>, but does not sit inside the class Array
|
||||||
|
val <T> Array<T>.isEmpty : Boolean get() = size == 0
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/**
|
||||||
|
* This is an example of a Type-Safe Groovy-style Builder
|
||||||
|
*
|
||||||
|
* Builders are good for declaratively describing data in your code.
|
||||||
|
* In this example we show how to describe an HTML page in Kotlin.
|
||||||
|
*
|
||||||
|
* See this page for details:
|
||||||
|
* http://confluence.jetbrains.net/display/Kotlin/Type-safe+Groovy-style+builders
|
||||||
|
*/
|
||||||
|
package html
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
val result =
|
||||||
|
html {
|
||||||
|
head {
|
||||||
|
title {+"XML encoding with Kotlin"}
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
h1 {+"XML encoding with Kotlin"}
|
||||||
|
p {+"this format can be used as an alternative markup to XML"}
|
||||||
|
|
||||||
|
// an element with attributes and text content
|
||||||
|
a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
|
||||||
|
|
||||||
|
// mixed content
|
||||||
|
p {
|
||||||
|
+"This is some"
|
||||||
|
b {+"mixed"}
|
||||||
|
+"text. For more see the"
|
||||||
|
a(href = "http://jetbrains.com/kotlin") {+"Kotlin"}
|
||||||
|
+"project"
|
||||||
|
}
|
||||||
|
p {+"some text"}
|
||||||
|
|
||||||
|
// content generated from command-line arguments
|
||||||
|
p {
|
||||||
|
+"Command line arguments were:"
|
||||||
|
ul {
|
||||||
|
for (arg in args)
|
||||||
|
li {+arg}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Element {
|
||||||
|
fun render(builder : StringBuilder, indent : String)
|
||||||
|
|
||||||
|
fun toString() : String? {
|
||||||
|
val builder = StringBuilder()
|
||||||
|
render(builder, "")
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TextElement(val text : String) : Element {
|
||||||
|
override fun render(builder : StringBuilder, indent : String) {
|
||||||
|
builder.append("$indent$text\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Tag(val name : String) : Element {
|
||||||
|
val children = ArrayList<Element>()
|
||||||
|
val attributes = HashMap<String, String>()
|
||||||
|
|
||||||
|
protected fun initTag<T : Element>(tag : T, init : T.() -> Unit) : T {
|
||||||
|
tag.init()
|
||||||
|
children.add(tag)
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(builder : StringBuilder, indent : String) {
|
||||||
|
builder.append("$indent<$name${renderAttributes()}>\n")
|
||||||
|
for (c in children) {
|
||||||
|
c.render(builder, indent + " ")
|
||||||
|
}
|
||||||
|
builder.append("$indent</$name>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderAttributes() : String? {
|
||||||
|
val builder = StringBuilder()
|
||||||
|
for (a in attributes.keySet()) {
|
||||||
|
builder.append(" $a=\"${attributes[a]}\"")
|
||||||
|
}
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class TagWithText(name : String) : Tag(name) {
|
||||||
|
fun String.plus() {
|
||||||
|
children.add(TextElement(this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HTML() : TagWithText("html") {
|
||||||
|
fun head(init : Head.() -> Unit) = initTag(Head(), init)
|
||||||
|
|
||||||
|
fun body(init : Body.() -> Unit) = initTag(Body(), init)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Head() : TagWithText("head") {
|
||||||
|
fun title(init : Title.() -> Unit) = initTag(Title(), init)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Title() : TagWithText("title")
|
||||||
|
|
||||||
|
abstract class BodyTag(name : String) : TagWithText(name) {
|
||||||
|
fun b(init : B.() -> Unit) = initTag(B(), init)
|
||||||
|
fun p(init : P.() -> Unit) = initTag(P(), init)
|
||||||
|
fun h1(init : H1.() -> Unit) = initTag(H1(), init)
|
||||||
|
fun ul(init : UL.() -> Unit) = initTag(UL(), init)
|
||||||
|
fun a(href : String, init : A.() -> Unit) {
|
||||||
|
val a = initTag(A(), init)
|
||||||
|
a.href = href
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Body() : BodyTag("body")
|
||||||
|
class UL() : BodyTag("ul") {
|
||||||
|
fun li(init : LI.() -> Unit) = initTag(LI(), init)
|
||||||
|
}
|
||||||
|
|
||||||
|
class B() : BodyTag("b")
|
||||||
|
class LI() : BodyTag("li")
|
||||||
|
class P() : BodyTag("p")
|
||||||
|
class H1() : BodyTag("h1")
|
||||||
|
class A() : BodyTag("a") {
|
||||||
|
public var href : String
|
||||||
|
get() = attributes["href"]
|
||||||
|
set(value) {
|
||||||
|
attributes["href"] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun html(init : HTML.() -> Unit) : HTML {
|
||||||
|
val html = HTML()
|
||||||
|
html.init()
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
// An excerpt from the Standard Library
|
||||||
|
fun <K, V> Map<K, V>.set(key : K, value : V) = this.put(key, value)
|
||||||
|
|
||||||
|
fun println(message : Any?) {
|
||||||
|
System.out?.println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun print(message : Any?) {
|
||||||
|
System.out?.print(message)
|
||||||
|
}
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
/**
|
||||||
|
* This is a straightforward implementation of The Game of Life
|
||||||
|
* See http://en.wikipedia.org/wiki/Conway's_Game_of_Life
|
||||||
|
*/
|
||||||
|
package life
|
||||||
|
|
||||||
|
import java.util.Collections.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A field where cells live. Effectively immutable
|
||||||
|
*/
|
||||||
|
class Field(
|
||||||
|
val width : Int,
|
||||||
|
val height : Int,
|
||||||
|
// This function tells the constructor which cells are alive
|
||||||
|
// if init(i, j) is true, the cell (i, j) is alive
|
||||||
|
init : (Int, Int) -> Boolean
|
||||||
|
) {
|
||||||
|
private val live : Array<Array<Boolean>> = Array(height) {i -> Array(width) {j -> init(i, j)}}
|
||||||
|
|
||||||
|
private fun liveCount(i : Int, j : Int)
|
||||||
|
= if (i in 0..height-1 &&
|
||||||
|
j in 0..width-1 &&
|
||||||
|
live[i][j]) 1 else 0
|
||||||
|
|
||||||
|
// How many neighbors of (i, j) are alive?
|
||||||
|
fun liveNeighbors(i : Int, j : Int) =
|
||||||
|
liveCount(i - 1, j - 1) +
|
||||||
|
liveCount(i - 1, j) +
|
||||||
|
liveCount(i - 1, j + 1) +
|
||||||
|
liveCount(i, j - 1) +
|
||||||
|
liveCount(i, j + 1) +
|
||||||
|
liveCount(i + 1, j - 1) +
|
||||||
|
liveCount(i + 1, j) +
|
||||||
|
liveCount(i + 1, j + 1)
|
||||||
|
|
||||||
|
// You can say field[i, j], and this function gets called
|
||||||
|
fun get(i : Int, j : Int) = live[i][j]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function takes the present state of the field
|
||||||
|
* and return a new field representing the next moment of time
|
||||||
|
*/
|
||||||
|
fun next(field : Field) : Field {
|
||||||
|
return Field(field.width, field.height) {i, j ->
|
||||||
|
val n = field.liveNeighbors(i, j)
|
||||||
|
if (field[i, j])
|
||||||
|
// (i, j) is alive
|
||||||
|
n in 2..3 // It remains alive iff it has 2 or 3 neighbors
|
||||||
|
else
|
||||||
|
// (i, j) is dead
|
||||||
|
n == 3 // A new cell is born if there are 3 neighbors alive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A few colony examples here */
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
// Simplistic demo
|
||||||
|
printField("***", 3)
|
||||||
|
// "Star burst"
|
||||||
|
printField("""
|
||||||
|
__*__
|
||||||
|
_***_
|
||||||
|
__*__
|
||||||
|
""", 10)
|
||||||
|
// Stable colony
|
||||||
|
printField("""
|
||||||
|
__*__
|
||||||
|
_*_*_
|
||||||
|
__*__
|
||||||
|
""", 3)
|
||||||
|
// Stable from the step 2
|
||||||
|
printField("""
|
||||||
|
__**__
|
||||||
|
__**__
|
||||||
|
__**__
|
||||||
|
""", 3)
|
||||||
|
// Oscillating colony
|
||||||
|
printField("""
|
||||||
|
__**__
|
||||||
|
__**__
|
||||||
|
__**__
|
||||||
|
__**__
|
||||||
|
""", 6)
|
||||||
|
// A fancier oscillating colony
|
||||||
|
printField("""
|
||||||
|
---------------
|
||||||
|
---***---***---
|
||||||
|
---------------
|
||||||
|
-*----*-*----*-
|
||||||
|
-*----*-*----*-
|
||||||
|
-*----*-*----*-
|
||||||
|
---***---***---
|
||||||
|
---------------
|
||||||
|
---***---***---
|
||||||
|
-*----*-*----*-
|
||||||
|
-*----*-*----*-
|
||||||
|
-*----*-*----*-
|
||||||
|
---------------
|
||||||
|
---***---***---
|
||||||
|
---------------
|
||||||
|
""", 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTILITIES
|
||||||
|
|
||||||
|
fun printField(s : String, steps : Int) {
|
||||||
|
var field = makeField(s)
|
||||||
|
for (step in 1..steps) {
|
||||||
|
println("Step: $step")
|
||||||
|
for (i in 0..field.height-1) {
|
||||||
|
for (j in 0..field.width-1) {
|
||||||
|
print(if (field[i, j]) "*" else " ")
|
||||||
|
}
|
||||||
|
println("")
|
||||||
|
}
|
||||||
|
field = next(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun makeField(s : String) : Field {
|
||||||
|
val lines = s.split("\n").sure()
|
||||||
|
val w = max<String?>(lines.toList(), comparator<String?> {o1, o2 ->
|
||||||
|
val l1 : Int = o1?.size ?: 0
|
||||||
|
val l2 = o2?.size ?: 0
|
||||||
|
l1 - l2
|
||||||
|
}).sure()
|
||||||
|
val data = Array(lines.size) {Array(w.size) {false}}
|
||||||
|
|
||||||
|
// workaround
|
||||||
|
for (i in data.indices) {
|
||||||
|
data[i] = Array(w.size) {false}
|
||||||
|
for (j in data[i].indices)
|
||||||
|
data[i][j] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for (line in lines.indices) {
|
||||||
|
for (x in lines[line].indices) {
|
||||||
|
val c = lines[line].sure()[x]
|
||||||
|
data[line][x] = c == '*'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Field(w.size, lines.size) {i, j -> data[i][j]}
|
||||||
|
}
|
||||||
|
|
||||||
|
// An excerpt from the Standard Library
|
||||||
|
val String?.indices : IntRange get() = IntRange(0, this.sure().size)
|
||||||
|
|
||||||
|
fun <K, V> Map<K, V>.set(k : K, v : V) { put(k, v) }
|
||||||
|
|
||||||
|
fun comparator<T> (f : (T, T) -> Int) : Comparator<T> = object : Comparator<T> {
|
||||||
|
override fun compare(o1 : T, o2 : T) : Int = f(o1, o2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun println(message : Any?) {
|
||||||
|
System.out?.println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun print(message : Any?) {
|
||||||
|
System.out?.print(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
val <T> Array<T>.isEmpty : Boolean get() = size == 0
|
||||||
|
|
||||||
|
fun <T, C: Collection<T>> Array<T>.to(result: C) : C {
|
||||||
|
for (elem in this)
|
||||||
|
result.add(elem)
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
/**
|
||||||
|
* Let's Walk Through a Maze.
|
||||||
|
*
|
||||||
|
* Imagine there is a maze whose walls are the big 'O' letters.
|
||||||
|
* Now, I stand where a big 'I' stands and some cool prize lies
|
||||||
|
* somewhere marked with a '$' sign. Like this:
|
||||||
|
*
|
||||||
|
* OOOOOOOOOOOOOOOOO
|
||||||
|
* O O
|
||||||
|
* O$ O O
|
||||||
|
* OOOOO O
|
||||||
|
* O O
|
||||||
|
* O OOOOOOOOOOOOOO
|
||||||
|
* O O I O
|
||||||
|
* O O
|
||||||
|
* OOOOOOOOOOOOOOOOO
|
||||||
|
*
|
||||||
|
* I want to get the prize, and this program helps me do so as soon
|
||||||
|
* as I possibly can by finding a shortest path through the maze.
|
||||||
|
*/
|
||||||
|
package maze
|
||||||
|
|
||||||
|
import java.util.Collections.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function looks for a path from max.start to maze.end through
|
||||||
|
* free space (a path does not go through walls). One can move only
|
||||||
|
* straightly up, down, left or right, no diagonal moves allowed.
|
||||||
|
*/
|
||||||
|
fun findPath(maze : Maze) : List<#(Int, Int)>? {
|
||||||
|
val previous = HashMap<#(Int, Int), #(Int, Int)>
|
||||||
|
|
||||||
|
val queue = LinkedList<#(Int, Int)>
|
||||||
|
val visited = HashSet<#(Int, Int)>
|
||||||
|
|
||||||
|
queue.offer(maze.start)
|
||||||
|
visited.add(maze.start)
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
val cell = queue.poll()
|
||||||
|
if (cell == maze.end) break
|
||||||
|
|
||||||
|
for (newCell in maze.neighbors(cell._1, cell._2)) {
|
||||||
|
if (newCell in visited) continue
|
||||||
|
previous[newCell] = cell
|
||||||
|
queue.offer(newCell)
|
||||||
|
visited.add(cell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous[maze.end] == null) return null
|
||||||
|
|
||||||
|
val path = ArrayList<#(Int, Int)>()
|
||||||
|
var current = previous[maze.end]
|
||||||
|
while (current != maze.start) {
|
||||||
|
path.add(0, current)
|
||||||
|
current = previous[current]
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find neighbors of the (i, j) cell that are not walls
|
||||||
|
*/
|
||||||
|
fun Maze.neighbors(i : Int, j : Int) : List<#(Int, Int)> {
|
||||||
|
val result = ArrayList<#(Int, Int)>
|
||||||
|
addIfFree(i - 1, j, result)
|
||||||
|
addIfFree(i, j - 1, result)
|
||||||
|
addIfFree(i + 1, j, result)
|
||||||
|
addIfFree(i, j + 1, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Maze.addIfFree(i : Int, j : Int, result : List<#(Int, Int)>) {
|
||||||
|
if (i !in 0..height-1) return
|
||||||
|
if (j !in 0..width-1) return
|
||||||
|
if (walls[i][j]) return
|
||||||
|
|
||||||
|
result.add(#(i, j))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data class that represents a maze
|
||||||
|
*/
|
||||||
|
class Maze(
|
||||||
|
// Number or columns
|
||||||
|
val width : Int,
|
||||||
|
// Number of rows
|
||||||
|
val height : Int,
|
||||||
|
// true for a wall, false for free space
|
||||||
|
val walls : Array<out Array<out Boolean>>,
|
||||||
|
// The starting point (must not be a wall)
|
||||||
|
val start : #(Int, Int),
|
||||||
|
// The target point (must not be a wall)
|
||||||
|
val end : #(Int, Int)
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A few maze examples here */
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
printMaze("I $")
|
||||||
|
printMaze("I O $")
|
||||||
|
printMaze("""
|
||||||
|
O $
|
||||||
|
O
|
||||||
|
O
|
||||||
|
O
|
||||||
|
O I
|
||||||
|
""")
|
||||||
|
printMaze("""
|
||||||
|
OOOOOOOOOOO
|
||||||
|
O $ O
|
||||||
|
OOOOOOO OOO
|
||||||
|
O O
|
||||||
|
OOOOO OOOOO
|
||||||
|
O O
|
||||||
|
O OOOOOOOOO
|
||||||
|
O OO
|
||||||
|
OOOOOO IO
|
||||||
|
""")
|
||||||
|
printMaze("""
|
||||||
|
OOOOOOOOOOOOOOOOO
|
||||||
|
O O
|
||||||
|
O$ O O
|
||||||
|
OOOOO O
|
||||||
|
O O
|
||||||
|
O OOOOOOOOOOOOOO
|
||||||
|
O O I O
|
||||||
|
O O
|
||||||
|
OOOOOOOOOOOOOOOOO
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTILITIES
|
||||||
|
|
||||||
|
fun printMaze(str : String) {
|
||||||
|
val maze = makeMaze(str)
|
||||||
|
|
||||||
|
println("Maze:")
|
||||||
|
val path = findPath(maze)
|
||||||
|
for (i in 0..maze.height - 1) {
|
||||||
|
for (j in 0..maze.width - 1) {
|
||||||
|
val cell = #(i, j)
|
||||||
|
print(
|
||||||
|
if (maze.walls[i][j]) "O"
|
||||||
|
else if (cell == maze.start) "I"
|
||||||
|
else if (cell == maze.end) "$"
|
||||||
|
else if (path != null && path.contains(cell)) "~"
|
||||||
|
else " "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
println("")
|
||||||
|
}
|
||||||
|
println("Result: " + if (path == null) "No path" else "Path found")
|
||||||
|
println("")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A maze is encoded in the string s: the big 'O' letters are walls.
|
||||||
|
* I stand where a big 'I' stands and the prize is marked with
|
||||||
|
* a '$' sign.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* OOOOOOOOOOOOOOOOO
|
||||||
|
* O O
|
||||||
|
* O$ O O
|
||||||
|
* OOOOO O
|
||||||
|
* O O
|
||||||
|
* O OOOOOOOOOOOOOO
|
||||||
|
* O O I O
|
||||||
|
* O O
|
||||||
|
* OOOOOOOOOOOOOOOOO
|
||||||
|
*/
|
||||||
|
fun makeMaze(s : String) : Maze {
|
||||||
|
val lines = s.split("\n").sure()
|
||||||
|
val w = max<String?>(lines.toList(), comparator<String?> {o1, o2 ->
|
||||||
|
val l1 : Int = o1?.size ?: 0
|
||||||
|
val l2 = o2?.size ?: 0
|
||||||
|
l1 - l2
|
||||||
|
}).sure()
|
||||||
|
val data = Array<Array<Boolean>>(lines.size) {Array<Boolean>(w.size) {false}}
|
||||||
|
|
||||||
|
var start : #(Int, Int)? = null
|
||||||
|
var end : #(Int, Int)? = null
|
||||||
|
|
||||||
|
for (line in lines.indices) {
|
||||||
|
for (x in lines[line].indices) {
|
||||||
|
val c = lines[line].sure()[x]
|
||||||
|
data[line][x] = c == 'O'
|
||||||
|
when (c) {
|
||||||
|
'I' -> start = #(line, x)
|
||||||
|
'$' -> end = #(line, x)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == null) {
|
||||||
|
throw IllegalArgumentException("No starting point in the maze (should be indicated with 'I')")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end == null) {
|
||||||
|
throw IllegalArgumentException("No goal point in the maze (should be indicated with a '$' sign)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Maze(w.size, lines.size, data, start.sure(), end.sure())
|
||||||
|
}
|
||||||
|
|
||||||
|
// An excerpt from the Standard Library
|
||||||
|
val String?.indices : IntRange get() = IntRange(0, this.sure().size)
|
||||||
|
|
||||||
|
fun <K, V> Map<K, V>.set(k : K, v : V) { put(k, v) }
|
||||||
|
|
||||||
|
fun comparator<T> (f : (T, T) -> Int) : Comparator<T> = object : Comparator<T> {
|
||||||
|
override fun compare(o1 : T, o2 : T) : Int = f(o1, o2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun println(message : Any?) {
|
||||||
|
System.out?.println(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun print(message : Any?) {
|
||||||
|
System.out?.print(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, C: Collection<T>> Array<T>.to(result: C) : C {
|
||||||
|
for (elem in this)
|
||||||
|
result.add(elem)
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
<project name="Kotlin" default="dist">
|
<project name="Kotlin" default="dist">
|
||||||
|
|
||||||
<property name="output" value="${basedir}/dist"/>
|
<property name="output" value="${basedir}/dist"/>
|
||||||
<property name="build.number" value="snapshot"/>
|
<property name="build.number" value="snapshot"/>
|
||||||
<property name="output.name" value="kotlin-${build.number}"/>
|
<property name="output.name" value="kotlin-${build.number}"/>
|
||||||
<property name="idea.sdk" value="${basedir}/ideaSDK"/>
|
<property name="idea.sdk" value="${basedir}/ideaSDK"/>
|
||||||
|
|
||||||
|
<import file="build-tools/build.xml" optional="false"/>
|
||||||
|
|
||||||
<path id="classpath">
|
<path id="classpath">
|
||||||
<fileset dir="${idea.sdk}" includes="*.jar"/>
|
<fileset dir="${idea.sdk}" includes="*.jar"/>
|
||||||
<fileset dir="${basedir}/lib" includes="*.jar"/>
|
<fileset dir="${basedir}/lib" includes="*.jar"/>
|
||||||
@@ -29,7 +32,7 @@
|
|||||||
|
|
||||||
<target name="compileRT">
|
<target name="compileRT">
|
||||||
<mkdir dir="${output}/classes/runtime"/>
|
<mkdir dir="${output}/classes/runtime"/>
|
||||||
<javac destdir="${output}/classes/runtime" debug="true" debuglevel="lines,vars,source">
|
<javac destdir="${output}/classes/runtime" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
|
||||||
<src path="${basedir}/stdlib/src"/>
|
<src path="${basedir}/stdlib/src"/>
|
||||||
<classpath refid="classpath"/>
|
<classpath refid="classpath"/>
|
||||||
</javac>
|
</javac>
|
||||||
@@ -55,10 +58,10 @@
|
|||||||
</jar>
|
</jar>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<target name="compile" depends="compileRT">
|
<target name="compile" depends="compileRT">
|
||||||
<mkdir dir="${output}/classes/compiler"/>
|
<mkdir dir="${output}/classes/compiler"/>
|
||||||
<javac destdir="${output}/classes/compiler" debug="true" debuglevel="lines,vars,source">
|
<javac destdir="${output}/classes/compiler" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
|
||||||
<src refid="sourcepath"/>
|
<src refid="sourcepath"/>
|
||||||
<classpath refid="classpath"/>
|
<classpath refid="classpath"/>
|
||||||
</javac>
|
</javac>
|
||||||
@@ -75,13 +78,13 @@
|
|||||||
<delete dir="${output}"/>
|
<delete dir="${output}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="dist" depends="clean,jarRT,jar">
|
<target name="dist" depends="clean,jarRT,jar,buildToolsJar">
|
||||||
<echo file="${output}/build.txt" message="${build.number}"/>
|
<echo file="${output}/build.txt" message="${build.number}"/>
|
||||||
<zip destfile="${output}/${output.name}.zip">
|
<zip destfile="${output}/${output.name}.zip">
|
||||||
<zipfileset prefix="kotlinc" file="${output}/build.txt"/>
|
<zipfileset prefix="kotlinc" file="${output}/build.txt"/>
|
||||||
<zipfileset prefix="kotlinc/license" dir="${basedir}/license"/>
|
<zipfileset prefix="kotlinc/license" dir="${basedir}/license"/>
|
||||||
<zipfileset prefix="kotlinc/bin" filemode="755" dir="${basedir}/compiler/cli/bin"/>
|
<zipfileset prefix="kotlinc/bin" filemode="755" dir="${basedir}/compiler/cli/bin"/>
|
||||||
<zipfileset prefix="kotlinc/lib" dir="${idea.sdk}"/>
|
<zipfileset prefix="kotlinc/lib" dir="${idea.sdk}" excludes="ant/**"/>
|
||||||
<zipfileset prefix="kotlinc/lib" dir="${basedir}/lib"/>
|
<zipfileset prefix="kotlinc/lib" dir="${basedir}/lib"/>
|
||||||
<zipfileset prefix="kotlinc/lib" dir="${output}" includes="*.jar"/>
|
<zipfileset prefix="kotlinc/lib" dir="${output}" includes="*.jar"/>
|
||||||
<zipfileset prefix="kotlinc/examples" dir="${basedir}/examples/src"/>
|
<zipfileset prefix="kotlinc/examples" dir="${basedir}/examples/src"/>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.resolve.java.JetSignatureUtils;
|
|||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
|
import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureReader;
|
import org.jetbrains.jet.rt.signature.JetSignatureReader;
|
||||||
|
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureWriter;
|
import org.jetbrains.jet.rt.signature.JetSignatureWriter;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
@@ -203,10 +204,20 @@ public class BothSignatureWriter {
|
|||||||
public void writeArrayEnd() {
|
public void writeArrayEnd() {
|
||||||
pop();
|
pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static JetSignatureVariance toJetSignatureVariance(Variance variance) {
|
||||||
|
switch (variance) {
|
||||||
|
case INVARIANT: return JetSignatureVariance.INVARIANT;
|
||||||
|
case IN_VARIANCE: return JetSignatureVariance.IN;
|
||||||
|
case OUT_VARIANCE: return JetSignatureVariance.OUT;
|
||||||
|
default: throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void writeTypeArgument(char c) {
|
public void writeTypeArgument(Variance variance) {
|
||||||
push(signatureVisitor().visitTypeArgument(c));
|
JetSignatureVariance jsVariance = toJetSignatureVariance(variance);
|
||||||
jetSignatureWriter.visitTypeArgument(c);
|
push(signatureVisitor().visitTypeArgument(jsVariance.getC()));
|
||||||
|
jetSignatureWriter.visitTypeArgument(jsVariance);
|
||||||
generic = true;
|
generic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1024,7 +1024,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) {
|
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) {
|
||||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
|
||||||
functionDescriptor = functionDescriptor.getOriginal();
|
functionDescriptor = functionDescriptor.getOriginal();
|
||||||
String owner;
|
String owner;
|
||||||
|
|
||||||
@@ -1092,30 +1092,32 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!(containingDeclaration instanceof JavaNamespaceDescriptor))
|
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||||
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
|
||||||
else
|
|
||||||
getter = null;
|
|
||||||
|
|
||||||
if (propertyDescriptor.getGetter() == null) {
|
if (propertyDescriptor.getGetter() == null) {
|
||||||
getter = null;
|
getter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getter == null && propertyDescriptor.getReceiverParameter().exists()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())) {
|
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())) {
|
||||||
setter = null;
|
setter = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(!(containingDeclaration instanceof JavaNamespaceDescriptor)) {
|
JvmPropertyAccessorSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
JvmPropertyAccessorSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null;
|
||||||
setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null;
|
|
||||||
} else {
|
|
||||||
setter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyDescriptor.getSetter() == null) {
|
if (propertyDescriptor.getSetter() == null) {
|
||||||
setter = null;
|
setter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (setter == null && propertyDescriptor.isVar() && propertyDescriptor.getReceiverParameter().exists()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,9 @@ public class FunctionCodegen {
|
|||||||
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
|
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
|
||||||
}
|
}
|
||||||
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, true);
|
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, true);
|
||||||
|
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(0) != null) {
|
||||||
|
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, jvmSignature.getKotlinParameterTypes().get(0).getKotlinSignature());
|
||||||
|
}
|
||||||
av.visitEnd();
|
av.visitEnd();
|
||||||
}
|
}
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ public class JetTypeMapper {
|
|||||||
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable());
|
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable());
|
||||||
for (TypeProjection proj : jetType.getArguments()) {
|
for (TypeProjection proj : jetType.getArguments()) {
|
||||||
// TODO: +-
|
// TODO: +-
|
||||||
signatureVisitor.writeTypeArgument('=');
|
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
|
||||||
mapType(proj.getType(), kind, signatureVisitor, true);
|
mapType(proj.getType(), kind, signatureVisitor, true);
|
||||||
signatureVisitor.writeTypeArgumentEnd();
|
signatureVisitor.writeTypeArgumentEnd();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ public class KotlinCompiler {
|
|||||||
@Argument(value = "help", alias = "h", description = "show help")
|
@Argument(value = "help", alias = "h", description = "show help")
|
||||||
public boolean help;
|
public boolean help;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void usage(PrintStream target) {
|
private static void usage(PrintStream target) {
|
||||||
target.println("Usage: KotlinCompiler [-output <outputDir>|-jar <jarFileName>] [-src <filename or dirname>|-module <module file>] [-includeRuntime] [-excludeStdlib]");
|
target.println("Usage: KotlinCompiler [-output <outputDir>|-jar <jarFileName>] [-src <filename or dirname>|-module <module file>] [-includeRuntime] [-excludeStdlib]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String ... args) {
|
||||||
System.setProperty("java.awt.headless", "true");
|
System.setProperty("java.awt.headless", "true");
|
||||||
Arguments arguments = new Arguments();
|
Arguments arguments = new Arguments();
|
||||||
try {
|
try {
|
||||||
@@ -53,7 +53,7 @@ public class KotlinCompiler {
|
|||||||
System.exit(1);
|
System.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.help) {
|
if (arguments.help) {
|
||||||
usage(System.out);
|
usage(System.out);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
|
|||||||
+24
-39
@@ -2,15 +2,26 @@ package org.jetbrains.jet.lang.resolve.java;
|
|||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.HierarchicalMethodSignature;
|
||||||
|
import com.intellij.psi.PsiClass;
|
||||||
|
import com.intellij.psi.PsiMethod;
|
||||||
|
import com.intellij.psi.PsiModifier;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -20,8 +31,6 @@ public class JavaClassMembersScope implements JetScope {
|
|||||||
private final JavaSemanticServices semanticServices;
|
private final JavaSemanticServices semanticServices;
|
||||||
private final boolean staticMembers;
|
private final boolean staticMembers;
|
||||||
private final DeclarationDescriptor containingDeclaration;
|
private final DeclarationDescriptor containingDeclaration;
|
||||||
private final Map<String, Set<FunctionDescriptor>> functionGroups = Maps.newHashMap();
|
|
||||||
private final Map<String, Set<VariableDescriptor>> variables = Maps.newHashMap();
|
|
||||||
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
|
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
|
||||||
private Collection<DeclarationDescriptor> allDescriptors;
|
private Collection<DeclarationDescriptor> allDescriptors;
|
||||||
|
|
||||||
@@ -76,7 +85,7 @@ public class JavaClassMembersScope implements JetScope {
|
|||||||
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, method);
|
FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, new PsiMethodWrapper(method));
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
allDescriptors.add(functionDescriptor);
|
allDescriptors.add(functionDescriptor);
|
||||||
}
|
}
|
||||||
@@ -117,14 +126,7 @@ public class JavaClassMembersScope implements JetScope {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Set<VariableDescriptor> getProperties(@NotNull String name) {
|
public Set<VariableDescriptor> getProperties(@NotNull String name) {
|
||||||
Set<VariableDescriptor> variableDescriptor = variables.get(name);
|
return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers);
|
||||||
if (variableDescriptor == null) {
|
|
||||||
variableDescriptor = doGetVariable(name);
|
|
||||||
if (variableDescriptor != null) {
|
|
||||||
variables.put(name, variableDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return variableDescriptor != null ? variableDescriptor : Collections.<VariableDescriptor>emptySet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -132,32 +134,15 @@ public class JavaClassMembersScope implements JetScope {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Set<VariableDescriptor> doGetVariable(String name) {
|
|
||||||
PsiField field = psiClass.findFieldByName(name, true);
|
|
||||||
if (field == null) return null;
|
|
||||||
if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field);
|
|
||||||
return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
|
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
|
||||||
Set<FunctionDescriptor> functionGroup = functionGroups.get(name);
|
return semanticServices.getDescriptorResolver().resolveFunctionGroup(
|
||||||
if (functionGroup == null) {
|
containingDeclaration,
|
||||||
functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup(
|
psiClass,
|
||||||
containingDeclaration,
|
staticMembers ? null : (ClassDescriptor) containingDeclaration,
|
||||||
psiClass,
|
name,
|
||||||
staticMembers ? null : (ClassDescriptor) containingDeclaration,
|
staticMembers);
|
||||||
name,
|
|
||||||
staticMembers);
|
|
||||||
functionGroups.put(name, functionGroup);
|
|
||||||
}
|
|
||||||
return functionGroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+242
-323
@@ -4,23 +4,24 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.HierarchicalMethodSignature;
|
|
||||||
import com.intellij.psi.JavaPsiFacade;
|
import com.intellij.psi.JavaPsiFacade;
|
||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiClass;
|
||||||
import com.intellij.psi.PsiClassType;
|
import com.intellij.psi.PsiClassType;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiEllipsisType;
|
import com.intellij.psi.PsiEllipsisType;
|
||||||
import com.intellij.psi.PsiField;
|
|
||||||
import com.intellij.psi.PsiJavaFile;
|
import com.intellij.psi.PsiJavaFile;
|
||||||
import com.intellij.psi.PsiMethod;
|
import com.intellij.psi.PsiMethod;
|
||||||
import com.intellij.psi.PsiModifier;
|
import com.intellij.psi.PsiModifier;
|
||||||
import com.intellij.psi.PsiModifierListOwner;
|
import com.intellij.psi.PsiModifierListOwner;
|
||||||
import com.intellij.psi.PsiPackage;
|
import com.intellij.psi.PsiPackage;
|
||||||
|
import com.intellij.psi.PsiPrimitiveType;
|
||||||
import com.intellij.psi.PsiType;
|
import com.intellij.psi.PsiType;
|
||||||
import com.intellij.psi.PsiTypeParameter;
|
import com.intellij.psi.PsiTypeParameter;
|
||||||
import com.intellij.psi.PsiTypeParameterListOwner;
|
import com.intellij.psi.PsiTypeParameterListOwner;
|
||||||
|
import com.intellij.psi.PsiTypeVariable;
|
||||||
|
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import jet.typeinfo.TypeInfoVariance;
|
import jet.typeinfo.TypeInfoVariance;
|
||||||
@@ -63,6 +64,8 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
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;
|
||||||
@@ -128,11 +131,12 @@ public class JavaDescriptorResolver {
|
|||||||
this.lowerBoundsForKotlin = lowerBoundsForKotlin;
|
this.lowerBoundsForKotlin = lowerBoundsForKotlin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static abstract class ResolverScopeData {
|
private static abstract class ResolverScopeData {
|
||||||
@Nullable
|
|
||||||
private Set<VariableDescriptor> properties;
|
|
||||||
protected boolean kotlin;
|
protected boolean kotlin;
|
||||||
|
|
||||||
|
private Map<String, NamedMembers> namedMembersMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ResolverClassData extends ResolverScopeData {
|
private static class ResolverClassData extends ResolverScopeData {
|
||||||
@@ -159,7 +163,6 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
private final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
|
private final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
|
||||||
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
||||||
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
|
|
||||||
protected final JavaPsiFacade javaFacade;
|
protected final JavaPsiFacade javaFacade;
|
||||||
protected final GlobalSearchScope javaSearchScope;
|
protected final GlobalSearchScope javaSearchScope;
|
||||||
protected final JavaSemanticServices semanticServices;
|
protected final JavaSemanticServices semanticServices;
|
||||||
@@ -737,15 +740,6 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
PsiType psiType = parameter.getPsiParameter().getType();
|
PsiType psiType = parameter.getPsiParameter().getType();
|
||||||
|
|
||||||
JetType varargElementType;
|
|
||||||
if (psiType instanceof PsiEllipsisType) {
|
|
||||||
PsiEllipsisType psiEllipsisType = (PsiEllipsisType) psiType;
|
|
||||||
varargElementType = semanticServices.getTypeTransformer().transformToType(psiEllipsisType.getComponentType());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
varargElementType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean nullable = parameter.getJetValueParameter().nullable();
|
boolean nullable = parameter.getJetValueParameter().nullable();
|
||||||
|
|
||||||
// TODO: must be very slow, make it lazy?
|
// TODO: must be very slow, make it lazy?
|
||||||
@@ -765,6 +759,14 @@ public class JavaDescriptorResolver {
|
|||||||
} else {
|
} else {
|
||||||
outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JetType varargElementType;
|
||||||
|
if (psiType instanceof PsiEllipsisType) {
|
||||||
|
varargElementType = semanticServices.getJetSemanticServices().getStandardLibrary().getArrayElementType(outType);
|
||||||
|
} else {
|
||||||
|
varargElementType = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (receiver) {
|
if (receiver) {
|
||||||
return JvmMethodParameterMeaning.receiver(outType);
|
return JvmMethodParameterMeaning.receiver(outType);
|
||||||
} else {
|
} else {
|
||||||
@@ -781,252 +783,135 @@ public class JavaDescriptorResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) {
|
|
||||||
VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field);
|
|
||||||
if (variableDescriptor != null) {
|
|
||||||
return variableDescriptor;
|
|
||||||
}
|
|
||||||
JetType type = semanticServices.getTypeTransformer().transformToType(field.getType());
|
|
||||||
boolean isFinal = field.hasModifierProperty(PsiModifier.FINAL);
|
|
||||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
|
||||||
containingDeclaration,
|
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
|
||||||
Modality.FINAL,
|
|
||||||
resolveVisibilityFromPsiModifiers(field),
|
|
||||||
!isFinal,
|
|
||||||
null,
|
|
||||||
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
|
|
||||||
field.getName(),
|
|
||||||
type);
|
|
||||||
semanticServices.getTrace().record(BindingContext.VARIABLE, field, propertyDescriptor);
|
|
||||||
fieldDescriptorCache.put(field, propertyDescriptor);
|
|
||||||
return propertyDescriptor;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static class PropertyKey {
|
|
||||||
@NotNull
|
|
||||||
private final String name;
|
|
||||||
//@NotNull
|
|
||||||
//private final PsiType type;
|
|
||||||
//@Nullable
|
|
||||||
//private final PsiType receiverType;
|
|
||||||
|
|
||||||
private PropertyKey(@NotNull String name /*, @NotNull PsiType type, @Nullable PsiType receiverType */) {
|
|
||||||
this.name = name;
|
|
||||||
//this.type = type;
|
|
||||||
//this.receiverType = receiverType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
|
|
||||||
PropertyKey that = (PropertyKey) o;
|
|
||||||
|
|
||||||
if (!name.equals(that.name)) return false;
|
|
||||||
//if (receiverType != null ? !receiverType.equals(that.receiverType) : that.receiverType != null)
|
|
||||||
// return false;
|
|
||||||
//if (!type.equals(that.type)) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int result = name.hashCode();
|
|
||||||
//result = 31 * result + type.hashCode();
|
|
||||||
//result = 31 * result + (receiverType != null ? receiverType.hashCode() : 0);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class MembersForProperty {
|
|
||||||
private PsiFieldWrapper field;
|
|
||||||
private PsiMethodWrapper setter;
|
|
||||||
private PsiMethodWrapper getter;
|
|
||||||
|
|
||||||
private PsiType type;
|
|
||||||
private PsiType receiverType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<PropertyKey, MembersForProperty> getMembersForProperties(@NotNull PsiClass clazz, boolean staticMembers, boolean kotlin) {
|
|
||||||
Map<PropertyKey, MembersForProperty> membersMap = Maps.newHashMap();
|
|
||||||
if (!kotlin) {
|
|
||||||
for (PsiField field : clazz.getFields()) {
|
|
||||||
if (field.getModifierList().hasExplicitModifier(PsiModifier.STATIC) != staticMembers) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MembersForProperty members = new MembersForProperty();
|
|
||||||
members.field = new PsiFieldWrapper(field);
|
|
||||||
members.type = field.getType();
|
|
||||||
membersMap.put(new PropertyKey(field.getName() /*, field.getType(), null*/), members);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PsiMethod psiMethod : clazz.getMethods()) {
|
|
||||||
PsiMethodWrapper method = new PsiMethodWrapper(psiMethod);
|
|
||||||
|
|
||||||
if (method.isStatic() != staticMembers) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method.isPrivate()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: "is" prefix
|
|
||||||
// TODO: remove getJavaClass
|
|
||||||
if (psiMethod.getName().startsWith(JvmAbi.GETTER_PREFIX)) {
|
|
||||||
|
|
||||||
// TODO: some java properties too
|
|
||||||
if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
|
|
||||||
|
|
||||||
if (psiMethod.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
PsiType receiverType;
|
|
||||||
if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) {
|
|
||||||
receiverType = method.getParameter(i).getPsiParameter().getType();
|
|
||||||
++i;
|
|
||||||
} else {
|
|
||||||
receiverType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) {
|
|
||||||
// TODO: store is reified
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != method.getParameters().size()) {
|
|
||||||
// TODO: report error properly
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
String propertyName = StringUtil.decapitalize(psiMethod.getName().substring(JvmAbi.GETTER_PREFIX.length()));
|
|
||||||
PropertyKey key = new PropertyKey(propertyName /*, psiMethod.getReturnType(), receiverType*/);
|
|
||||||
MembersForProperty members = membersMap.get(key);
|
|
||||||
if (members == null) {
|
|
||||||
members = new MembersForProperty();
|
|
||||||
membersMap.put(key, members);
|
|
||||||
}
|
|
||||||
members.getter = new PsiMethodWrapper(psiMethod);
|
|
||||||
|
|
||||||
// TODO: check conflicts with setter
|
|
||||||
members.type = psiMethod.getReturnType();
|
|
||||||
members.receiverType = receiverType;
|
|
||||||
}
|
|
||||||
} else if (psiMethod.getName().startsWith(JvmAbi.SETTER_PREFIX)) {
|
|
||||||
|
|
||||||
if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
|
|
||||||
if (psiMethod.getParameterList().getParametersCount() == 0) {
|
|
||||||
// TODO: report error properly
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
PsiType receiverType = null;
|
|
||||||
PsiParameterWrapper p1 = method.getParameter(0);
|
|
||||||
if (p1.getJetValueParameter().receiver()) {
|
|
||||||
receiverType = p1.getPsiParameter().getType();
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 1 != psiMethod.getParameterList().getParametersCount()) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
PsiType propertyType = psiMethod.getParameterList().getParameters()[i].getType();
|
|
||||||
|
|
||||||
String propertyName = StringUtil.decapitalize(psiMethod.getName().substring(JvmAbi.SETTER_PREFIX.length()));
|
|
||||||
PropertyKey key = new PropertyKey(propertyName /*, propertyType, receiverType*/);
|
|
||||||
MembersForProperty members = membersMap.get(key);
|
|
||||||
if (members == null) {
|
|
||||||
members = new MembersForProperty();
|
|
||||||
membersMap.put(key, members);
|
|
||||||
}
|
|
||||||
members.setter = new PsiMethodWrapper(psiMethod);
|
|
||||||
|
|
||||||
// TODO: check conflicts with getter
|
|
||||||
members.type = propertyType;
|
|
||||||
members.receiverType = receiverType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return membersMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<VariableDescriptor> resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) {
|
public Set<VariableDescriptor> resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) {
|
||||||
Set<VariableDescriptor> r = Sets.newHashSet();
|
ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
|
||||||
// TODO: slow
|
|
||||||
Set<VariableDescriptor> variables = resolveFieldGroup(owner, psiClass, staticMembers);
|
|
||||||
for (VariableDescriptor variable : variables) {
|
|
||||||
if (variable.getName().equals(fieldName)) {
|
|
||||||
r.add(variable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName);
|
||||||
|
if (namedMembers == null) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveNamedGroupProperties(owner, staticMembers, namedMembers, fieldName);
|
||||||
|
|
||||||
|
return namedMembers.propertyDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
|
public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
|
||||||
|
|
||||||
ResolverScopeData scopeData;
|
ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
|
||||||
if (owner instanceof JavaNamespaceDescriptor) {
|
|
||||||
scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName());
|
|
||||||
} else if (owner instanceof ClassDescriptor) {
|
|
||||||
scopeData = classDescriptorCache.get(psiClass.getQualifiedName());
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
if (scopeData == null) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scopeData.properties != null) {
|
|
||||||
return scopeData.properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<VariableDescriptor> descriptors = Sets.newHashSet();
|
Set<VariableDescriptor> descriptors = Sets.newHashSet();
|
||||||
Map<PropertyKey, MembersForProperty> membersForProperties = getMembersForProperties(psiClass, staticMembers, scopeData.kotlin);
|
Map<String, NamedMembers> membersForProperties = scopeData.namedMembersMap;
|
||||||
for (Map.Entry<PropertyKey, MembersForProperty> entry : membersForProperties.entrySet()) {
|
for (Map.Entry<String, NamedMembers> entry : membersForProperties.entrySet()) {
|
||||||
//VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field);
|
NamedMembers namedMembers = entry.getValue();
|
||||||
//if (variableDescriptor != null) {
|
if (namedMembers.propertyAccessors == null) {
|
||||||
// return variableDescriptor;
|
continue;
|
||||||
//}
|
}
|
||||||
String propertyName = entry.getKey().name;
|
|
||||||
PsiType propertyType = entry.getValue().type;
|
String propertyName = entry.getKey();
|
||||||
PsiType receiverType = entry.getValue().receiverType;
|
|
||||||
MembersForProperty members = entry.getValue();
|
|
||||||
|
|
||||||
|
resolveNamedGroupProperties(owner, staticMembers, namedMembers, propertyName);
|
||||||
|
descriptors.addAll(namedMembers.propertyDescriptors);
|
||||||
|
}
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object key(TypeSource typeSource) {
|
||||||
|
if (typeSource == null) {
|
||||||
|
return "";
|
||||||
|
} else if (typeSource.getTypeString().length() > 0) {
|
||||||
|
return typeSource.getTypeString();
|
||||||
|
} else {
|
||||||
|
if (typeSource.getPsiType() instanceof PsiClassType) {
|
||||||
|
return ((PsiClassType) typeSource.getPsiType()).getClassName();
|
||||||
|
} else if (typeSource.getPsiType() instanceof PsiPrimitiveType) {
|
||||||
|
return typeSource.getPsiType().getPresentableText();
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("" + typeSource.getPsiType().getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object propertyKeyForGrouping(PropertyAccessorData propertyAccessor) {
|
||||||
|
Object type = key(propertyAccessor.getType());
|
||||||
|
Object receiverType = key(propertyAccessor.getReceiverType());
|
||||||
|
return Pair.create(type, receiverType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveNamedGroupProperties(DeclarationDescriptor owner, boolean staticMembers, NamedMembers namedMembers, String propertyName) {
|
||||||
|
if (namedMembers.propertyDescriptors != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (namedMembers.propertyAccessors == null) {
|
||||||
|
namedMembers.propertyDescriptors = Collections.emptySet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<TypeParameterDescriptor> classTypeParameters;
|
||||||
|
if (!staticMembers) {
|
||||||
|
classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters();
|
||||||
|
} else {
|
||||||
|
classTypeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters);
|
||||||
|
|
||||||
|
class GroupingValue {
|
||||||
|
PropertyAccessorData getter;
|
||||||
|
PropertyAccessorData setter;
|
||||||
|
PropertyAccessorData field;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Object, GroupingValue> map = new HashMap<Object, GroupingValue>();
|
||||||
|
|
||||||
|
for (PropertyAccessorData propertyAccessor : namedMembers.propertyAccessors) {
|
||||||
|
|
||||||
|
Object key = propertyKeyForGrouping(propertyAccessor);
|
||||||
|
|
||||||
|
GroupingValue value = map.get(key);
|
||||||
|
if (value == null) {
|
||||||
|
value = new GroupingValue();
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyAccessor.isGetter()) {
|
||||||
|
if (value.getter != null) {
|
||||||
|
throw new IllegalStateException("oops, duplicate key");
|
||||||
|
}
|
||||||
|
value.getter = propertyAccessor;
|
||||||
|
} else if (propertyAccessor.isSetter()) {
|
||||||
|
if (value.setter != null) {
|
||||||
|
throw new IllegalStateException("oops, duplicate key");
|
||||||
|
}
|
||||||
|
value.setter = propertyAccessor;
|
||||||
|
} else if (propertyAccessor.isField()) {
|
||||||
|
if (value.field != null) {
|
||||||
|
throw new IllegalStateException("oops, duplicate key");
|
||||||
|
}
|
||||||
|
value.field = propertyAccessor;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Set<VariableDescriptor> r = new HashSet<VariableDescriptor>();
|
||||||
|
|
||||||
|
for (GroupingValue members : map.values()) {
|
||||||
boolean isFinal;
|
boolean isFinal;
|
||||||
if (members.setter == null && members.getter == null) {
|
if (members.setter == null && members.getter == null) {
|
||||||
isFinal = false;
|
isFinal = false;
|
||||||
} else if (members.getter != null) {
|
} else if (members.getter != null) {
|
||||||
isFinal = members.getter.isFinal();
|
isFinal = members.getter.getMember().isFinal();
|
||||||
} else if (members.setter != null) {
|
} else if (members.setter != null) {
|
||||||
isFinal = members.setter.isFinal();
|
isFinal = members.setter.getMember().isFinal();
|
||||||
} else {
|
} else {
|
||||||
isFinal = false;
|
isFinal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PsiMemberWrapper anyMember;
|
PropertyAccessorData anyMember;
|
||||||
if (members.getter != null) {
|
if (members.getter != null) {
|
||||||
anyMember = members.getter;
|
anyMember = members.getter;
|
||||||
} else if (members.field != null) {
|
} else if (members.field != null) {
|
||||||
@@ -1036,10 +921,10 @@ public class JavaDescriptorResolver {
|
|||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isVar;
|
boolean isVar;
|
||||||
if (members.getter == null && members.setter == null) {
|
if (members.getter == null && members.setter == null) {
|
||||||
isVar = true;
|
isVar = !members.field.getMember().isFinal();
|
||||||
} else {
|
} else {
|
||||||
isVar = members.setter != null;
|
isVar = members.setter != null;
|
||||||
}
|
}
|
||||||
@@ -1048,11 +933,11 @@ public class JavaDescriptorResolver {
|
|||||||
owner,
|
owner,
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
|
isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
|
||||||
resolveVisibilityFromPsiModifiers(anyMember.psiMember),
|
resolveVisibilityFromPsiModifiers(anyMember.getMember().psiMember),
|
||||||
isVar,
|
isVar,
|
||||||
false,
|
false,
|
||||||
propertyName);
|
propertyName);
|
||||||
|
|
||||||
PropertyGetterDescriptor getterDescriptor = null;
|
PropertyGetterDescriptor getterDescriptor = null;
|
||||||
PropertySetterDescriptor setterDescriptor = null;
|
PropertySetterDescriptor setterDescriptor = null;
|
||||||
if (members.getter != null) {
|
if (members.getter != null) {
|
||||||
@@ -1061,89 +946,124 @@ public class JavaDescriptorResolver {
|
|||||||
if (members.setter != null) {
|
if (members.setter != null) {
|
||||||
setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
|
setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
|
|
||||||
|
|
||||||
final List<TypeParameterDescriptor> classTypeParameters;
|
propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
|
||||||
if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) {
|
|
||||||
classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters();
|
|
||||||
} else {
|
|
||||||
classTypeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
|
||||||
}
|
|
||||||
TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters);
|
|
||||||
|
|
||||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
||||||
|
|
||||||
if (members.setter != null) {
|
if (members.setter != null) {
|
||||||
// call ugly code with side effects
|
PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember();
|
||||||
typeParameters = resolveMethodTypeParameters(members.setter, propertyDescriptor.getSetter(), typeVariableResolver);
|
|
||||||
|
if (anyMember == members.setter) {
|
||||||
|
typeParameters = resolveMethodTypeParameters(method, setterDescriptor, typeVariableResolver);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (members.getter != null) {
|
if (members.getter != null) {
|
||||||
// call ugly code with side effects
|
PsiMethodWrapper method = (PsiMethodWrapper) members.getter.getMember();
|
||||||
typeParameters = resolveMethodTypeParameters(members.getter, propertyDescriptor.getGetter(), typeVariableResolver);
|
|
||||||
|
if (anyMember == members.getter) {
|
||||||
|
typeParameters = resolveMethodTypeParameters(method, getterDescriptor, typeVariableResolver);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType receiverJetType;
|
List<TypeParameterDescriptor> typeParametersForReceiver = new ArrayList<TypeParameterDescriptor>();
|
||||||
if (receiverType == null) {
|
typeParametersForReceiver.addAll(classTypeParameters);
|
||||||
receiverJetType = null;
|
typeParametersForReceiver.addAll(typeParameters);
|
||||||
|
TypeVariableResolver typeVariableResolverForPropertyInternals = new TypeParameterListTypeVariableResolver(typeParametersForReceiver);
|
||||||
|
|
||||||
|
JetType propertyType;
|
||||||
|
if (anyMember.getType().getTypeString().length() > 0) {
|
||||||
|
propertyType = semanticServices.getTypeTransformer().transformToType(anyMember.getType().getTypeString(), typeVariableResolverForPropertyInternals);
|
||||||
} else {
|
} else {
|
||||||
receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType);
|
propertyType = semanticServices.getTypeTransformer().transformToType(anyMember.getType().getPsiType());
|
||||||
|
}
|
||||||
|
|
||||||
|
JetType receiverType;
|
||||||
|
if (anyMember.getReceiverType() == null) {
|
||||||
|
receiverType = null;
|
||||||
|
} else if (anyMember.getReceiverType().getTypeString().length() > 0) {
|
||||||
|
receiverType = semanticServices.getTypeTransformer().transformToType(anyMember.getReceiverType().getTypeString(), typeVariableResolverForPropertyInternals);
|
||||||
|
} else {
|
||||||
|
receiverType = semanticServices.getTypeTransformer().transformToType(anyMember.getReceiverType().getPsiType());
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType type = semanticServices.getTypeTransformer().transformToType(propertyType);
|
|
||||||
|
|
||||||
propertyDescriptor.setType(
|
propertyDescriptor.setType(
|
||||||
type,
|
propertyType,
|
||||||
typeParameters,
|
typeParameters,
|
||||||
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
|
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
|
||||||
receiverJetType
|
receiverType
|
||||||
);
|
);
|
||||||
if (getterDescriptor != null) {
|
if (getterDescriptor != null) {
|
||||||
getterDescriptor.initialize(type);
|
getterDescriptor.initialize(propertyType);
|
||||||
}
|
}
|
||||||
if (setterDescriptor != null) {
|
if (setterDescriptor != null) {
|
||||||
// TODO: initialize
|
// TODO: initialize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.getMember().psiMember, propertyDescriptor);
|
||||||
|
|
||||||
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor);
|
r.add(propertyDescriptor);
|
||||||
//fieldDescriptorCache.put(field, propertyDescriptor);
|
|
||||||
descriptors.add(propertyDescriptor);
|
|
||||||
}
|
}
|
||||||
scopeData.properties = descriptors;
|
|
||||||
return descriptors;
|
namedMembers.propertyDescriptors = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveNamedGroupFunctions(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, boolean staticMembers, NamedMembers namedMembers, String functionName) {
|
||||||
|
if (namedMembers.functionDescriptors != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (namedMembers.methods == null) {
|
||||||
|
namedMembers.functionDescriptors = Collections.emptySet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<FunctionDescriptor> functionDescriptors = new HashSet<FunctionDescriptor>(namedMembers.methods.size());
|
||||||
|
for (PsiMethodWrapper method : namedMembers.methods) {
|
||||||
|
functionDescriptors.add(resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutorForGenericSuperclasses, method));
|
||||||
|
}
|
||||||
|
namedMembers.functionDescriptors = functionDescriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResolverScopeData getResolverScopeData(DeclarationDescriptor owner, PsiClassWrapper psiClass) {
|
||||||
|
ResolverScopeData scopeData;
|
||||||
|
boolean staticMembers;
|
||||||
|
if (owner instanceof JavaNamespaceDescriptor) {
|
||||||
|
scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName());
|
||||||
|
staticMembers = true;
|
||||||
|
} else if (owner instanceof ClassDescriptor) {
|
||||||
|
scopeData = classDescriptorCache.get(psiClass.getQualifiedName());
|
||||||
|
staticMembers = false;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
if (scopeData == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scopeData.namedMembersMap == null) {
|
||||||
|
scopeData.namedMembersMap = JavaDescriptorResolverHelper.getNamedMembers(psiClass, staticMembers, scopeData.kotlin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return scopeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
|
public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
|
||||||
Set<FunctionDescriptor> writableFunctionGroup = Sets.newLinkedHashSet();
|
|
||||||
final Collection<HierarchicalMethodSignature> signatures = psiClass.getVisibleSignatures();
|
ResolverScopeData resolverScopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
|
||||||
|
|
||||||
|
Map<String, NamedMembers> namedMembersMap = resolverScopeData.namedMembersMap;
|
||||||
|
|
||||||
|
NamedMembers namedMembers = namedMembersMap.get(methodName);
|
||||||
|
if (namedMembers == null || namedMembers.methods == null) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor);
|
TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor);
|
||||||
for (HierarchicalMethodSignature signature: signatures) {
|
resolveNamedGroupFunctions(owner, psiClass, typeSubstitutor, staticMembers, namedMembers, methodName);
|
||||||
if (!methodName.equals(signature.getName())) {
|
|
||||||
continue;
|
return namedMembers.functionDescriptors;
|
||||||
}
|
|
||||||
|
|
||||||
FunctionDescriptor substitutedFunctionDescriptor = resolveHierarchicalSignatureToFunction(owner, psiClass, staticMembers, typeSubstitutor, signature);
|
|
||||||
if (substitutedFunctionDescriptor != null) {
|
|
||||||
writableFunctionGroup.add(substitutedFunctionDescriptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return writableFunctionGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private FunctionDescriptor resolveHierarchicalSignatureToFunction(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers, TypeSubstitutor typeSubstitutor, HierarchicalMethodSignature signature) {
|
|
||||||
PsiMethod method = signature.getMethod();
|
|
||||||
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutor, method);
|
|
||||||
// if (functionDescriptor != null && !staticMembers) {
|
|
||||||
// for (HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) {
|
|
||||||
// ((FunctionDescriptorImpl) functionDescriptor).addOverriddenFunction(resolveHierarchicalSignatureToFunction(owner, superSignature.getMethod().getContainingClass(), false, typeSubstitutor, superSignature));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return functionDescriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) {
|
public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) {
|
||||||
@@ -1178,16 +1098,15 @@ public class JavaDescriptorResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod psiMethod) {
|
public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethodWrapper method) {
|
||||||
PsiMethodWrapper method = new PsiMethodWrapper(psiMethod);
|
|
||||||
|
|
||||||
PsiType returnType = psiMethod.getReturnType();
|
PsiType returnType = method.getReturnType();
|
||||||
if (returnType == null) {
|
if (returnType == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
FunctionDescriptor functionDescriptor = methodDescriptorCache.get(psiMethod);
|
FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method.getPsiMethod());
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
if (psiMethod.getContainingClass() != psiClass) {
|
if (method.getPsiMethod().getContainingClass() != psiClass) {
|
||||||
functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses);
|
functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses);
|
||||||
}
|
}
|
||||||
return functionDescriptor;
|
return functionDescriptor;
|
||||||
@@ -1238,11 +1157,11 @@ public class JavaDescriptorResolver {
|
|||||||
DeclarationDescriptor classDescriptor;
|
DeclarationDescriptor classDescriptor;
|
||||||
final List<TypeParameterDescriptor> classTypeParameters;
|
final List<TypeParameterDescriptor> classTypeParameters;
|
||||||
if (method.isStatic()) {
|
if (method.isStatic()) {
|
||||||
classDescriptor = resolveNamespace(psiMethod.getContainingClass());
|
classDescriptor = resolveNamespace(method.getPsiMethod().getContainingClass());
|
||||||
classTypeParameters = Collections.emptyList();
|
classTypeParameters = Collections.emptyList();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ClassDescriptor classClassDescriptor = resolveClass(psiMethod.getContainingClass());
|
ClassDescriptor classClassDescriptor = resolveClass(method.getPsiMethod().getContainingClass());
|
||||||
classDescriptor = classClassDescriptor;
|
classDescriptor = classClassDescriptor;
|
||||||
classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters();
|
classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters();
|
||||||
}
|
}
|
||||||
@@ -1252,14 +1171,14 @@ public class JavaDescriptorResolver {
|
|||||||
NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl(
|
NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl(
|
||||||
owner,
|
owner,
|
||||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||||
psiMethod.getName()
|
method.getName()
|
||||||
);
|
);
|
||||||
methodDescriptorCache.put(psiMethod, functionDescriptorImpl);
|
methodDescriptorCache.put(method.getPsiMethod(), functionDescriptorImpl);
|
||||||
|
|
||||||
// TODO: add outer classes
|
// TODO: add outer classes
|
||||||
TypeParameterListTypeVariableResolver typeVariableResolverForParameters = new TypeParameterListTypeVariableResolver(classTypeParameters);
|
TypeParameterListTypeVariableResolver typeVariableResolverForParameters = new TypeParameterListTypeVariableResolver(classTypeParameters);
|
||||||
|
|
||||||
final List<TypeParameterDescriptor> methodTypeParameters = resolveMethodTypeParameters(new PsiMethodWrapper(psiMethod), functionDescriptorImpl, typeVariableResolverForParameters);
|
final List<TypeParameterDescriptor> methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl, typeVariableResolverForParameters);
|
||||||
|
|
||||||
class MethodTypeVariableResolver implements TypeVariableResolver {
|
class MethodTypeVariableResolver implements TypeVariableResolver {
|
||||||
|
|
||||||
@@ -1288,12 +1207,12 @@ public class JavaDescriptorResolver {
|
|||||||
methodTypeParameters,
|
methodTypeParameters,
|
||||||
valueParameterDescriptors.descriptors,
|
valueParameterDescriptors.descriptors,
|
||||||
makeReturnType(returnType, method, new MethodTypeVariableResolver()),
|
makeReturnType(returnType, method, new MethodTypeVariableResolver()),
|
||||||
Modality.convertFromFlags(psiMethod.hasModifierProperty(PsiModifier.ABSTRACT), !psiMethod.hasModifierProperty(PsiModifier.FINAL)),
|
Modality.convertFromFlags(method.getPsiMethod().hasModifierProperty(PsiModifier.ABSTRACT), !method.isFinal()),
|
||||||
resolveVisibilityFromPsiModifiers(psiMethod)
|
resolveVisibilityFromPsiModifiers(method.getPsiMethod())
|
||||||
);
|
);
|
||||||
semanticServices.getTrace().record(BindingContext.FUNCTION, psiMethod, functionDescriptorImpl);
|
semanticServices.getTrace().record(BindingContext.FUNCTION, method.getPsiMethod(), functionDescriptorImpl);
|
||||||
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
|
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
|
||||||
if (psiMethod.getContainingClass() != psiClass) {
|
if (method.getPsiMethod().getContainingClass() != psiClass) {
|
||||||
substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses);
|
substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses);
|
||||||
}
|
}
|
||||||
return substitutedFunctionDescriptor;
|
return substitutedFunctionDescriptor;
|
||||||
@@ -1301,7 +1220,7 @@ public class JavaDescriptorResolver {
|
|||||||
|
|
||||||
private List<TypeParameterDescriptor> resolveMethodTypeParameters(
|
private List<TypeParameterDescriptor> resolveMethodTypeParameters(
|
||||||
@NotNull PsiMethodWrapper method,
|
@NotNull PsiMethodWrapper method,
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull DeclarationDescriptor functionDescriptor,
|
||||||
@NotNull TypeVariableResolver classTypeVariableResolver) {
|
@NotNull TypeVariableResolver classTypeVariableResolver) {
|
||||||
if (method.getJetMethod().typeParameters().length() > 0) {
|
if (method.getJetMethod().typeParameters().length() > 0) {
|
||||||
List<TypeParameterDescriptor> r = resolveMethodTypeParametersFromJetSignature(
|
List<TypeParameterDescriptor> r = resolveMethodTypeParametersFromJetSignature(
|
||||||
@@ -1319,7 +1238,7 @@ public class JavaDescriptorResolver {
|
|||||||
* @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, MutableClassDescriptorLite)
|
* @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, MutableClassDescriptorLite)
|
||||||
*/
|
*/
|
||||||
private List<TypeParameterDescriptor> resolveMethodTypeParametersFromJetSignature(String jetSignature, final PsiMethod method,
|
private List<TypeParameterDescriptor> resolveMethodTypeParametersFromJetSignature(String jetSignature, final PsiMethod method,
|
||||||
final FunctionDescriptor functionDescriptor, final TypeVariableResolver classTypeVariableResolver)
|
final DeclarationDescriptor functionDescriptor, final TypeVariableResolver classTypeVariableResolver)
|
||||||
{
|
{
|
||||||
final List<TypeParameterDescriptor> r = new ArrayList<TypeParameterDescriptor>();
|
final List<TypeParameterDescriptor> r = new ArrayList<TypeParameterDescriptor>();
|
||||||
|
|
||||||
@@ -1400,7 +1319,7 @@ public class JavaDescriptorResolver {
|
|||||||
ownerOwner = classDescriptor;
|
ownerOwner = classDescriptor;
|
||||||
substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes(classDescriptor);
|
substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes(classDescriptor);
|
||||||
}
|
}
|
||||||
FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, psiMethod);
|
FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, new PsiMethodWrapper(psiMethod));
|
||||||
return resolveTypeParameter(functionDescriptor, typeParameter);
|
return resolveTypeParameter(functionDescriptor, typeParameter);
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Unknown parent type: " + owner);
|
throw new IllegalStateException("Unknown parent type: " + owner);
|
||||||
|
|||||||
+167
@@ -0,0 +1,167 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
|
import com.intellij.psi.HierarchicalMethodSignature;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
class JavaDescriptorResolverHelper {
|
||||||
|
|
||||||
|
|
||||||
|
private static class Builder {
|
||||||
|
private final PsiClassWrapper psiClass;
|
||||||
|
private final boolean staticMembers;
|
||||||
|
private final boolean kotlin;
|
||||||
|
|
||||||
|
private Map<String, NamedMembers> namedMembersMap = new HashMap<String, NamedMembers>();
|
||||||
|
|
||||||
|
private Builder(PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) {
|
||||||
|
this.psiClass = psiClass;
|
||||||
|
this.staticMembers = staticMembers;
|
||||||
|
this.kotlin = kotlin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
processFields();
|
||||||
|
processMethods();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NamedMembers getNamedMembers(String name) {
|
||||||
|
NamedMembers r = namedMembersMap.get(name);
|
||||||
|
if (r == null) {
|
||||||
|
r = new NamedMembers();
|
||||||
|
r.name = name;
|
||||||
|
namedMembersMap.put(name, r);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFields() {
|
||||||
|
if (!kotlin) {
|
||||||
|
for (PsiFieldWrapper field : psiClass.getFields()) {
|
||||||
|
if (field.isStatic() != staticMembers) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.isPrivate()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedMembers namedMembers = getNamedMembers(field.getName());
|
||||||
|
|
||||||
|
TypeSource type = new TypeSource("", field.getType());
|
||||||
|
namedMembers.addPropertyAccessor(new PropertyAccessorData(field, type, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMethods() {
|
||||||
|
for (HierarchicalMethodSignature method0 : psiClass.getPsiClass().getVisibleSignatures()) {
|
||||||
|
|
||||||
|
PsiMethodWrapper method = new PsiMethodWrapper(method0.getMethod());
|
||||||
|
|
||||||
|
if (method.isStatic() != staticMembers) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.isPrivate()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: "is" prefix
|
||||||
|
// TODO: remove getJavaClass
|
||||||
|
if (method.getName().startsWith(JvmAbi.GETTER_PREFIX)) {
|
||||||
|
|
||||||
|
// TODO: some java properties too
|
||||||
|
if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
|
||||||
|
|
||||||
|
if (method.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
TypeSource receiverType;
|
||||||
|
if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) {
|
||||||
|
PsiParameterWrapper receiverParameter = method.getParameter(i);
|
||||||
|
receiverType = new TypeSource(receiverParameter.getJetValueParameter().type(), receiverParameter.getPsiParameter().getType());
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
receiverType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) {
|
||||||
|
// TODO: store is reified
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != method.getParameters().size()) {
|
||||||
|
// TODO: report error properly
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.GETTER_PREFIX.length()));
|
||||||
|
NamedMembers members = getNamedMembers(propertyName);
|
||||||
|
|
||||||
|
// TODO: what if returnType == null?
|
||||||
|
TypeSource propertyType = new TypeSource(method.getJetMethod().propertyType(), method.getReturnType());
|
||||||
|
|
||||||
|
members.addPropertyAccessor(new PropertyAccessorData(method, true, propertyType, receiverType));
|
||||||
|
}
|
||||||
|
} else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) {
|
||||||
|
|
||||||
|
if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
|
||||||
|
if (method.getParameters().size() == 0) {
|
||||||
|
// TODO: report error properly
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
TypeSource receiverType = null;
|
||||||
|
PsiParameterWrapper p1 = method.getParameter(0);
|
||||||
|
if (p1.getJetValueParameter().receiver()) {
|
||||||
|
receiverType = new TypeSource(p1.getJetValueParameter().type(), p1.getPsiParameter().getType());
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 != method.getParameters().size()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
PsiParameterWrapper propertyTypeParameter = method.getParameter(i);
|
||||||
|
TypeSource propertyType = new TypeSource(method.getJetMethod().propertyType(), propertyTypeParameter.getPsiParameter().getType());
|
||||||
|
|
||||||
|
String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.SETTER_PREFIX.length()));
|
||||||
|
NamedMembers members = getNamedMembers(propertyName);
|
||||||
|
|
||||||
|
members.addPropertyAccessor(new PropertyAccessorData(method, false, propertyType, receiverType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method.getJetMethod().kind() != JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
|
||||||
|
NamedMembers namedMembers = getNamedMembers(method.getName());
|
||||||
|
namedMembers.addMethod(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Map<String, NamedMembers> getNamedMembers(@NotNull PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) {
|
||||||
|
Builder builder = new Builder(psiClass, staticMembers, kotlin);
|
||||||
|
builder.run();
|
||||||
|
return builder.namedMembersMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+9
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
@@ -46,6 +47,14 @@ public class JavaSemanticServices {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public ClassDescriptor getKotlinClassDescriptor(String qualifiedName) {
|
public ClassDescriptor getKotlinClassDescriptor(String qualifiedName) {
|
||||||
|
if (qualifiedName.startsWith("jet.")) {
|
||||||
|
ClassDescriptor r = (ClassDescriptor) jetSemanticServices.getStandardLibrary().getLibraryScope().getClassifier(qualifiedName.substring("jet.".length()));
|
||||||
|
if (r == null) {
|
||||||
|
// TODO: better error
|
||||||
|
//throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
return getTrace().get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, qualifiedName);
|
return getTrace().get(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, qualifiedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-4
@@ -108,11 +108,14 @@ public class JavaTypeTransformer {
|
|||||||
for (TypeParameterDescriptor parameter : parameters) {
|
for (TypeParameterDescriptor parameter : parameters) {
|
||||||
arguments.add(TypeUtils.makeStarProjection(parameter));
|
arguments.add(TypeUtils.makeStarProjection(parameter));
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
|
List<TypeParameterDescriptor> parameters = descriptor.getTypeConstructor().getParameters();
|
||||||
PsiType[] psiArguments = classType.getParameters();
|
PsiType[] psiArguments = classType.getParameters();
|
||||||
for (int i = 0, psiArgumentsLength = psiArguments.length; i < psiArgumentsLength; i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
PsiType psiArgument = psiArguments[i];
|
PsiType psiArgument = psiArguments[i];
|
||||||
TypeParameterDescriptor typeParameterDescriptor = descriptor.getTypeConstructor().getParameters().get(i);
|
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||||
|
|
||||||
arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor));
|
arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +190,6 @@ public class JavaTypeTransformer {
|
|||||||
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
||||||
classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType));
|
classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType));
|
||||||
}
|
}
|
||||||
//classDescriptorMap.put("java.lang.Object", standardLibrary.get
|
|
||||||
classDescriptorMap.put("java.lang.String", standardLibrary.getString());
|
classDescriptorMap.put("java.lang.String", standardLibrary.getString());
|
||||||
}
|
}
|
||||||
return classDescriptorMap;
|
return classDescriptorMap;
|
||||||
|
|||||||
+31
-8
@@ -12,11 +12,14 @@ import org.jetbrains.jet.lang.types.TypeProjection;
|
|||||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
|
import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
|
||||||
|
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
|
||||||
import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Stepan Koltsov
|
* @author Stepan Koltsov
|
||||||
@@ -75,6 +78,26 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
|
|||||||
|
|
||||||
this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName);
|
this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName);
|
||||||
|
|
||||||
|
if (this.classDescriptor == null && ourName.equals("java.lang.Object")) {
|
||||||
|
this.classDescriptor = JetStandardClasses.getAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classDescriptor == null) {
|
||||||
|
// TODO: this is the worst code in Kotlin project
|
||||||
|
Matcher matcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
classDescriptor = JetStandardClasses.getFunction(Integer.parseInt(matcher.group(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classDescriptor == null) {
|
||||||
|
Matcher matcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
classDescriptor = JetStandardClasses.getTuple(Integer.parseInt(matcher.group(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (this.classDescriptor == null) {
|
if (this.classDescriptor == null) {
|
||||||
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
|
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
|
||||||
}
|
}
|
||||||
@@ -86,22 +109,22 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
|
|||||||
this.typeArguments = new ArrayList<TypeProjection>();
|
this.typeArguments = new ArrayList<TypeProjection>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Variance parseVariance(char wildcard) {
|
private static Variance parseVariance(JetSignatureVariance variance) {
|
||||||
switch (wildcard) {
|
switch (variance) {
|
||||||
case '=': return Variance.INVARIANT;
|
case INVARIANT: return Variance.INVARIANT;
|
||||||
case '+': return Variance.OUT_VARIANCE;
|
case OUT: return Variance.OUT_VARIANCE;
|
||||||
case '-': return Variance.IN_VARIANCE;
|
case IN: return Variance.IN_VARIANCE;
|
||||||
default: throw new IllegalStateException();
|
default: throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
|
public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance variance) {
|
||||||
return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) {
|
return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(@NotNull JetType jetType) {
|
protected void done(@NotNull JetType jetType) {
|
||||||
typeArguments.add(new TypeProjection(parseVariance(wildcard), jetType));
|
typeArguments.add(new TypeProjection(parseVariance(variance), jetType));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -142,7 +165,7 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
|
|||||||
classDescriptor.getTypeConstructor(),
|
classDescriptor.getTypeConstructor(),
|
||||||
nullable,
|
nullable,
|
||||||
typeArguments,
|
typeArguments,
|
||||||
ErrorUtils.getErrorScope());
|
classDescriptor.getMemberScope(typeArguments));
|
||||||
done(jetType);
|
done(jetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass;
|
||||||
|
import com.intellij.psi.PsiMethod;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
class NamedMembers {
|
||||||
|
String name;
|
||||||
|
List<PsiMethodWrapper> methods;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
PsiFieldWrapper field;
|
||||||
|
@Nullable
|
||||||
|
List<PropertyAccessorData> propertyAccessors;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private PsiClass nestedClasses;
|
||||||
|
|
||||||
|
Set<VariableDescriptor> propertyDescriptors;
|
||||||
|
Set<FunctionDescriptor> functionDescriptors;
|
||||||
|
|
||||||
|
void addMethod(PsiMethodWrapper method) {
|
||||||
|
if (methods == null) {
|
||||||
|
methods = new ArrayList<PsiMethodWrapper>();
|
||||||
|
}
|
||||||
|
methods.add(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPropertyAccessor(PropertyAccessorData propertyAccessorData) {
|
||||||
|
if (propertyAccessors == null) {
|
||||||
|
propertyAccessors = new ArrayList<PropertyAccessorData>();
|
||||||
|
}
|
||||||
|
propertyAccessors.add(propertyAccessorData);
|
||||||
|
}
|
||||||
|
}
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
class PropertyAccessorData {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final PsiMemberWrapper member;
|
||||||
|
private final boolean getter;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final TypeSource type;
|
||||||
|
@Nullable
|
||||||
|
private final TypeSource receiverType;
|
||||||
|
|
||||||
|
|
||||||
|
PropertyAccessorData(@NotNull PsiMethodWrapper method, boolean getter, @NotNull TypeSource type, @Nullable TypeSource receiverType) {
|
||||||
|
this.member = method;
|
||||||
|
this.type = type;
|
||||||
|
this.receiverType = receiverType;
|
||||||
|
this.getter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyAccessorData(@NotNull PsiFieldWrapper field, @NotNull TypeSource type, @Nullable TypeSource receiverType) {
|
||||||
|
this.member = field;
|
||||||
|
this.type = type;
|
||||||
|
this.receiverType = receiverType;
|
||||||
|
this.getter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PsiMemberWrapper getMember() {
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TypeSource getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public TypeSource getReceiverType() {
|
||||||
|
return receiverType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGetter() {
|
||||||
|
return member instanceof PsiMethodWrapper && getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSetter() {
|
||||||
|
return member instanceof PsiMethodWrapper && !getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isField() {
|
||||||
|
return member instanceof PsiFieldWrapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass;
|
||||||
|
import com.intellij.psi.PsiField;
|
||||||
|
import com.intellij.psi.PsiMethod;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
public class PsiClassWrapper {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final PsiClass psiClass;
|
||||||
|
|
||||||
|
public PsiClassWrapper(@NotNull PsiClass psiClass) {
|
||||||
|
this.psiClass = psiClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PsiMethodWrapper> methods;
|
||||||
|
@NotNull
|
||||||
|
public List<PsiMethodWrapper> getMethods() {
|
||||||
|
if (methods == null) {
|
||||||
|
PsiMethod[] psiMethods = psiClass.getMethods();
|
||||||
|
List<PsiMethodWrapper> methods = new ArrayList<PsiMethodWrapper>(psiMethods.length);
|
||||||
|
for (PsiMethod psiMethod : psiMethods) {
|
||||||
|
methods.add(new PsiMethodWrapper(psiMethod));
|
||||||
|
}
|
||||||
|
this.methods = methods;
|
||||||
|
}
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PsiFieldWrapper> fields;
|
||||||
|
@NotNull
|
||||||
|
public List<PsiFieldWrapper> getFields() {
|
||||||
|
if (fields == null) {
|
||||||
|
PsiField[] psiFields = psiClass.getFields();
|
||||||
|
List<PsiFieldWrapper> fields = new ArrayList<PsiFieldWrapper>(psiFields.length);
|
||||||
|
for (PsiField psiField : psiFields) {
|
||||||
|
fields.add(new PsiFieldWrapper(psiField));
|
||||||
|
}
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQualifiedName() {
|
||||||
|
return psiClass.getQualifiedName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PsiClass getPsiClass() {
|
||||||
|
return psiClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.jetbrains.jet.lang.resolve.java;
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiField;
|
||||||
import com.intellij.psi.PsiMember;
|
import com.intellij.psi.PsiMember;
|
||||||
|
import com.intellij.psi.PsiType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,4 +12,12 @@ public class PsiFieldWrapper extends PsiMemberWrapper {
|
|||||||
public PsiFieldWrapper(@NotNull PsiMember psiMember) {
|
public PsiFieldWrapper(@NotNull PsiMember psiMember) {
|
||||||
super(psiMember);
|
super(psiMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PsiField getPsiField() {
|
||||||
|
return (PsiField) psiMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PsiType getType() {
|
||||||
|
return getPsiField().getType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
/**
|
/**
|
||||||
* @author Stepan Koltsov
|
* @author Stepan Koltsov
|
||||||
*/
|
*/
|
||||||
public class PsiMemberWrapper {
|
public abstract class PsiMemberWrapper {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected final PsiMember psiMember;
|
protected final PsiMember psiMember;
|
||||||
@@ -23,7 +23,11 @@ public class PsiMemberWrapper {
|
|||||||
public boolean isPrivate() {
|
public boolean isPrivate() {
|
||||||
return psiMember.hasModifierProperty(PsiModifier.PRIVATE);
|
return psiMember.hasModifierProperty(PsiModifier.PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFinal() {
|
||||||
|
return psiMember.hasModifierProperty(PsiModifier.FINAL);
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return psiMember.getName();
|
return psiMember.getName();
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-4
@@ -3,7 +3,9 @@ package org.jetbrains.jet.lang.resolve.java;
|
|||||||
import com.intellij.psi.PsiMethod;
|
import com.intellij.psi.PsiMethod;
|
||||||
import com.intellij.psi.PsiModifier;
|
import com.intellij.psi.PsiModifier;
|
||||||
import com.intellij.psi.PsiParameter;
|
import com.intellij.psi.PsiParameter;
|
||||||
|
import com.intellij.psi.PsiType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation;
|
import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation;
|
import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation;
|
||||||
|
|
||||||
@@ -37,10 +39,6 @@ public class PsiMethodWrapper extends PsiMemberWrapper {
|
|||||||
return getParameters().get(i);
|
return getParameters().get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFinal() {
|
|
||||||
return psiMember.hasModifierProperty(PsiModifier.FINAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JetMethodAnnotation jetMethod;
|
private JetMethodAnnotation jetMethod;
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetMethodAnnotation getJetMethod() {
|
public JetMethodAnnotation getJetMethod() {
|
||||||
@@ -59,8 +57,17 @@ public class PsiMethodWrapper extends PsiMemberWrapper {
|
|||||||
return jetConstructor;
|
return jetConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAbstract() {
|
||||||
|
return psiMember.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public PsiMethod getPsiMethod() {
|
public PsiMethod getPsiMethod() {
|
||||||
return (PsiMethod) psiMember;
|
return (PsiMethod) psiMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public PsiType getReturnType() {
|
||||||
|
return getPsiMethod().getReturnType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve.java;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Stepan Koltsov
|
||||||
|
*/
|
||||||
|
class TypeSource {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final String typeString;
|
||||||
|
@NotNull
|
||||||
|
private final PsiType psiType;
|
||||||
|
|
||||||
|
TypeSource(@NotNull String typeString, @NotNull PsiType psiType) {
|
||||||
|
this.typeString = typeString;
|
||||||
|
this.psiType = psiType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getTypeString() {
|
||||||
|
return typeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public PsiType getPsiType() {
|
||||||
|
return psiType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ 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;
|
||||||
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
|
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
|
||||||
|
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||||
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 org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
@@ -37,6 +38,15 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
private List<TypeParameterDescriptor> typeParemeters;
|
private List<TypeParameterDescriptor> typeParemeters;
|
||||||
private PropertyGetterDescriptor getter;
|
private PropertyGetterDescriptor getter;
|
||||||
private PropertySetterDescriptor setter;
|
private PropertySetterDescriptor setter;
|
||||||
|
|
||||||
|
private PropertyDescriptor() {
|
||||||
|
super(ErrorUtils.getErrorClass(), Collections.<AnnotationDescriptor>emptyList(), "dummy");
|
||||||
|
this.modality = null;
|
||||||
|
this.visibility = null;
|
||||||
|
this.isVar = false;
|
||||||
|
this.isObject = false;
|
||||||
|
this.original = null;
|
||||||
|
}
|
||||||
|
|
||||||
private PropertyDescriptor(
|
private PropertyDescriptor(
|
||||||
@Nullable PropertyDescriptor original,
|
@Nullable PropertyDescriptor original,
|
||||||
@@ -243,4 +253,8 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
propertyDescriptor.initialize(newGetter, newSetter);
|
propertyDescriptor.initialize(newGetter, newSetter);
|
||||||
return propertyDescriptor;
|
return propertyDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PropertyDescriptor createDummy() {
|
||||||
|
return new PropertyDescriptor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -73,7 +73,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
this,
|
this,
|
||||||
annotations,
|
annotations,
|
||||||
false,
|
false,
|
||||||
"&" + name,
|
name,
|
||||||
Collections.<TypeParameterDescriptor>emptyList(),
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
upperBounds);
|
upperBounds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class JetVisibilityChecker {
|
||||||
|
/**
|
||||||
|
* @param locationOwner owner of the call site
|
||||||
|
* @param subject the descriptor whose visibility is being checked
|
||||||
|
* @return <code>true</code> iff subject is visible locationOwner
|
||||||
|
*/
|
||||||
|
public boolean isVisible(@NotNull DeclarationDescriptor locationOwner, @NotNull DeclarationDescriptor subject) {
|
||||||
|
// TODO : stub implementation
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -100,13 +100,7 @@ public class TypeResolver {
|
|||||||
int expectedArgumentCount = parameters.size();
|
int expectedArgumentCount = parameters.size();
|
||||||
int actualArgumentCount = arguments.size();
|
int actualArgumentCount = arguments.size();
|
||||||
if (ErrorUtils.isError(typeConstructor)) {
|
if (ErrorUtils.isError(typeConstructor)) {
|
||||||
result[0] = new JetTypeImpl(
|
result[0] = ErrorUtils.createErrorType("??");
|
||||||
annotations,
|
|
||||||
typeConstructor,
|
|
||||||
nullable,
|
|
||||||
arguments, // TODO : review
|
|
||||||
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (actualArgumentCount != expectedArgumentCount) {
|
if (actualArgumentCount != expectedArgumentCount) {
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ import java.util.*;
|
|||||||
public class ErrorUtils {
|
public class ErrorUtils {
|
||||||
|
|
||||||
private static final ModuleDescriptor ERROR_MODULE = new ModuleDescriptor("<ERROR MODULE>");
|
private static final ModuleDescriptor ERROR_MODULE = new ModuleDescriptor("<ERROR MODULE>");
|
||||||
private static final JetScope ERROR_SCOPE = new JetScope() {
|
|
||||||
|
|
||||||
|
private static final JetScope ERROR_SCOPE = new ErrorScope();
|
||||||
|
|
||||||
|
public static class ErrorScope implements JetScope {
|
||||||
|
|
||||||
|
private ErrorScope() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassifierDescriptor getClassifier(@NotNull String name) {
|
public ClassifierDescriptor getClassifier(@NotNull String name) {
|
||||||
@@ -82,7 +88,7 @@ public class ErrorUtils {
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
private static final ClassDescriptorImpl ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.<AnnotationDescriptor>emptyList(), "<ERROR CLASS>") {
|
private static final ClassDescriptorImpl ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.<AnnotationDescriptor>emptyList(), "<ERROR CLASS>") {
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -96,6 +102,12 @@ public class ErrorUtils {
|
|||||||
public Modality getModality() {
|
public Modality getModality() {
|
||||||
return Modality.OPEN;
|
return Modality.OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public ClassDescriptor substitute(TypeSubstitutor substitutor) {
|
||||||
|
return ERROR_CLASS;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Set<FunctionDescriptor> ERROR_FUNCTION_GROUP = Collections.singleton(createErrorFunction(0, Collections.<JetType>emptyList()));
|
private static final Set<FunctionDescriptor> ERROR_FUNCTION_GROUP = Collections.singleton(createErrorFunction(0, Collections.<JetType>emptyList()));
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class JetStandardLibrary {
|
|||||||
private EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType;
|
private EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType;
|
||||||
private EnumMap<PrimitiveType, JetType> primitiveTypeToNullableArrayJetType;
|
private EnumMap<PrimitiveType, JetType> primitiveTypeToNullableArrayJetType;
|
||||||
private Map<JetType, JetType> primitiveJetTypeToJetArrayType;
|
private Map<JetType, JetType> primitiveJetTypeToJetArrayType;
|
||||||
|
private Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
|
||||||
|
|
||||||
private JetStandardLibrary(@NotNull Project project) {
|
private JetStandardLibrary(@NotNull Project project) {
|
||||||
// TODO : review
|
// TODO : review
|
||||||
@@ -147,6 +148,7 @@ public class JetStandardLibrary {
|
|||||||
primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
|
primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
|
||||||
primitiveTypeToNullableArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
|
primitiveTypeToNullableArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
|
||||||
primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
|
primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
|
||||||
|
jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>();
|
||||||
|
|
||||||
for (PrimitiveType primitive : PrimitiveType.values()) {
|
for (PrimitiveType primitive : PrimitiveType.values()) {
|
||||||
makePrimitive(primitive);
|
makePrimitive(primitive);
|
||||||
@@ -167,6 +169,7 @@ public class JetStandardLibrary {
|
|||||||
primitiveTypeToArrayJetType.put(primitiveType, arrayType);
|
primitiveTypeToArrayJetType.put(primitiveType, arrayType);
|
||||||
primitiveTypeToNullableArrayJetType.put(primitiveType, TypeUtils.makeNullable(arrayType));
|
primitiveTypeToNullableArrayJetType.put(primitiveType, TypeUtils.makeNullable(arrayType));
|
||||||
primitiveJetTypeToJetArrayType.put(type, arrayType);
|
primitiveJetTypeToJetArrayType.put(type, arrayType);
|
||||||
|
jetArrayTypeToPrimitiveJetType.put(arrayType, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -334,6 +337,22 @@ public class JetStandardLibrary {
|
|||||||
getArray().getMemberScope(types)
|
getArray().getMemberScope(types)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetType getArrayElementType(@NotNull JetType arrayType) {
|
||||||
|
// make non-null?
|
||||||
|
if (arrayType.getConstructor().getDeclarationDescriptor() == getArray()) {
|
||||||
|
if (arrayType.getArguments().size() != 1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return arrayType.getArguments().get(0).getType();
|
||||||
|
}
|
||||||
|
JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(arrayType);
|
||||||
|
if (primitiveType == null) {
|
||||||
|
throw new IllegalStateException("not array: " + arrayType);
|
||||||
|
}
|
||||||
|
return primitiveType;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetType getIterableType(@NotNull JetType argument) {
|
public JetType getIterableType(@NotNull JetType argument) {
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
|
|||||||
|
|
||||||
public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, @NotNull List<TypeProjection> arguments, JetScope memberScope) {
|
public JetTypeImpl(List<AnnotationDescriptor> annotations, TypeConstructor constructor, boolean nullable, @NotNull List<TypeProjection> arguments, JetScope memberScope) {
|
||||||
super(annotations);
|
super(annotations);
|
||||||
|
|
||||||
|
if (memberScope instanceof ErrorUtils.ErrorScope) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
this.constructor = constructor;
|
this.constructor = constructor;
|
||||||
this.nullable = nullable;
|
this.nullable = nullable;
|
||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
|
|||||||
@@ -100,6 +100,9 @@ public class TypeUtils {
|
|||||||
if (type.isNullable() == nullable) {
|
if (type.isNullable() == nullable) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
if (ErrorUtils.isErrorType(type)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), nullable, type.getArguments(), type.getMemberScope());
|
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), nullable, type.getArguments(), type.getMemberScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +288,9 @@ public class TypeUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) {
|
public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) {
|
||||||
|
if (ErrorUtils.isError(classDescriptor)) {
|
||||||
|
return ErrorUtils.createErrorType("This is very helpful diagnostics message");
|
||||||
|
}
|
||||||
List<TypeProjection> arguments = getDefaultTypeProjections(classDescriptor.getTypeConstructor().getParameters());
|
List<TypeProjection> arguments = getDefaultTypeProjections(classDescriptor.getTypeConstructor().getParameters());
|
||||||
return new JetTypeImpl(
|
return new JetTypeImpl(
|
||||||
Collections.<AnnotationDescriptor>emptyList(),
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
final class FieldAsVar {
|
||||||
|
public int f;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class FieldAsVar() {
|
||||||
|
var f: Int = 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
final class FinalFieldAsVal {
|
||||||
|
public final int f = 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class FinalFieldAsVal() {
|
||||||
|
val f: Int = 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public final class Simple {
|
||||||
|
public Simple() { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class Simple()
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
final class TwoFields {
|
||||||
|
int a;
|
||||||
|
short b;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class TwoFields() {
|
||||||
|
var a: Int = 1
|
||||||
|
var b: Short = 2;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user