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"
|
||||
|
||||
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/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">
|
||||
|
||||
<property name="output" value="${basedir}/dist"/>
|
||||
<property name="build.number" value="snapshot"/>
|
||||
<property name="output.name" value="kotlin-${build.number}"/>
|
||||
<property name="idea.sdk" value="${basedir}/ideaSDK"/>
|
||||
|
||||
<import file="build-tools/build.xml" optional="false"/>
|
||||
|
||||
<path id="classpath">
|
||||
<fileset dir="${idea.sdk}" includes="*.jar"/>
|
||||
<fileset dir="${basedir}/lib" includes="*.jar"/>
|
||||
@@ -29,7 +32,7 @@
|
||||
|
||||
<target name="compileRT">
|
||||
<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"/>
|
||||
<classpath refid="classpath"/>
|
||||
</javac>
|
||||
@@ -55,10 +58,10 @@
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<target name="compile" depends="compileRT">
|
||||
<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"/>
|
||||
<classpath refid="classpath"/>
|
||||
</javac>
|
||||
@@ -75,13 +78,13 @@
|
||||
<delete dir="${output}"/>
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="clean,jarRT,jar">
|
||||
<target name="dist" depends="clean,jarRT,jar,buildToolsJar">
|
||||
<echo file="${output}/build.txt" message="${build.number}"/>
|
||||
<zip destfile="${output}/${output.name}.zip">
|
||||
<zipfileset prefix="kotlinc" file="${output}/build.txt"/>
|
||||
<zipfileset prefix="kotlinc/license" dir="${basedir}/license"/>
|
||||
<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="${output}" includes="*.jar"/>
|
||||
<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.rt.signature.JetSignatureAdapter;
|
||||
import org.jetbrains.jet.rt.signature.JetSignatureReader;
|
||||
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
|
||||
import org.jetbrains.jet.rt.signature.JetSignatureWriter;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
@@ -203,10 +204,20 @@ public class BothSignatureWriter {
|
||||
public void writeArrayEnd() {
|
||||
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) {
|
||||
push(signatureVisitor().visitTypeArgument(c));
|
||||
jetSignatureWriter.visitTypeArgument(c);
|
||||
public void writeTypeArgument(Variance variance) {
|
||||
JetSignatureVariance jsVariance = toJetSignatureVariance(variance);
|
||||
push(signatureVisitor().visitTypeArgument(jsVariance.getC()));
|
||||
jetSignatureWriter.visitTypeArgument(jsVariance);
|
||||
generic = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1024,7 +1024,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) {
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
|
||||
functionDescriptor = functionDescriptor.getOriginal();
|
||||
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();
|
||||
else
|
||||
getter = null;
|
||||
|
||||
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod();
|
||||
|
||||
if (propertyDescriptor.getGetter() == null) {
|
||||
getter = null;
|
||||
}
|
||||
|
||||
if (getter == null && propertyDescriptor.getReceiverParameter().exists()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())) {
|
||||
setter = null;
|
||||
}
|
||||
else {
|
||||
if(!(containingDeclaration instanceof JavaNamespaceDescriptor)) {
|
||||
JvmPropertyAccessorSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null;
|
||||
} else {
|
||||
setter = null;
|
||||
}
|
||||
JvmPropertyAccessorSignature jvmMethodSignature = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
setter = jvmMethodSignature != null ? jvmMethodSignature.getJvmMethodSignature().getAsmMethod() : null;
|
||||
|
||||
if (propertyDescriptor.getSetter() == 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_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();
|
||||
}
|
||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||
|
||||
@@ -298,7 +298,7 @@ public class JetTypeMapper {
|
||||
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable());
|
||||
for (TypeProjection proj : jetType.getArguments()) {
|
||||
// TODO: +-
|
||||
signatureVisitor.writeTypeArgument('=');
|
||||
signatureVisitor.writeTypeArgument(proj.getProjectionKind());
|
||||
mapType(proj.getType(), kind, signatureVisitor, true);
|
||||
signatureVisitor.writeTypeArgumentEnd();
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@ public class KotlinCompiler {
|
||||
@Argument(value = "help", alias = "h", description = "show help")
|
||||
public boolean help;
|
||||
}
|
||||
|
||||
|
||||
private static void usage(PrintStream target) {
|
||||
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");
|
||||
Arguments arguments = new Arguments();
|
||||
try {
|
||||
@@ -53,7 +53,7 @@ public class KotlinCompiler {
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (arguments.help) {
|
||||
usage(System.out);
|
||||
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.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.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
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.receivers.ReceiverDescriptor;
|
||||
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
|
||||
@@ -20,8 +31,6 @@ public class JavaClassMembersScope implements JetScope {
|
||||
private final JavaSemanticServices semanticServices;
|
||||
private final boolean staticMembers;
|
||||
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 Collection<DeclarationDescriptor> allDescriptors;
|
||||
|
||||
@@ -76,7 +85,7 @@ public class JavaClassMembersScope implements JetScope {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
continue;
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, method);
|
||||
FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, new PsiMethodWrapper(method));
|
||||
if (functionDescriptor != null) {
|
||||
allDescriptors.add(functionDescriptor);
|
||||
}
|
||||
@@ -117,14 +126,7 @@ public class JavaClassMembersScope implements JetScope {
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<VariableDescriptor> getProperties(@NotNull String name) {
|
||||
Set<VariableDescriptor> variableDescriptor = variables.get(name);
|
||||
if (variableDescriptor == null) {
|
||||
variableDescriptor = doGetVariable(name);
|
||||
if (variableDescriptor != null) {
|
||||
variables.put(name, variableDescriptor);
|
||||
}
|
||||
}
|
||||
return variableDescriptor != null ? variableDescriptor : Collections.<VariableDescriptor>emptySet();
|
||||
return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,32 +134,15 @@ public class JavaClassMembersScope implements JetScope {
|
||||
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
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
|
||||
Set<FunctionDescriptor> functionGroup = functionGroups.get(name);
|
||||
if (functionGroup == null) {
|
||||
functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup(
|
||||
containingDeclaration,
|
||||
psiClass,
|
||||
staticMembers ? null : (ClassDescriptor) containingDeclaration,
|
||||
name,
|
||||
staticMembers);
|
||||
functionGroups.put(name, functionGroup);
|
||||
}
|
||||
return functionGroup;
|
||||
return semanticServices.getDescriptorResolver().resolveFunctionGroup(
|
||||
containingDeclaration,
|
||||
psiClass,
|
||||
staticMembers ? null : (ClassDescriptor) containingDeclaration,
|
||||
name,
|
||||
staticMembers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+242
-323
@@ -4,23 +4,24 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
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.psi.HierarchicalMethodSignature;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiEllipsisType;
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiTypeParameter;
|
||||
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.GlobalSearchScope;
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
@@ -63,6 +64,8 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -128,11 +131,12 @@ public class JavaDescriptorResolver {
|
||||
this.lowerBoundsForKotlin = lowerBoundsForKotlin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static abstract class ResolverScopeData {
|
||||
@Nullable
|
||||
private Set<VariableDescriptor> properties;
|
||||
protected boolean kotlin;
|
||||
|
||||
private Map<String, NamedMembers> namedMembersMap;
|
||||
}
|
||||
|
||||
private static class ResolverClassData extends ResolverScopeData {
|
||||
@@ -159,7 +163,6 @@ public class JavaDescriptorResolver {
|
||||
|
||||
private final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
|
||||
protected final JavaPsiFacade javaFacade;
|
||||
protected final GlobalSearchScope javaSearchScope;
|
||||
protected final JavaSemanticServices semanticServices;
|
||||
@@ -737,15 +740,6 @@ public class JavaDescriptorResolver {
|
||||
|
||||
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();
|
||||
|
||||
// TODO: must be very slow, make it lazy?
|
||||
@@ -765,6 +759,14 @@ public class JavaDescriptorResolver {
|
||||
} else {
|
||||
outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||
}
|
||||
|
||||
JetType varargElementType;
|
||||
if (psiType instanceof PsiEllipsisType) {
|
||||
varargElementType = semanticServices.getJetSemanticServices().getStandardLibrary().getArrayElementType(outType);
|
||||
} else {
|
||||
varargElementType = null;
|
||||
}
|
||||
|
||||
if (receiver) {
|
||||
return JvmMethodParameterMeaning.receiver(outType);
|
||||
} 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) {
|
||||
Set<VariableDescriptor> r = Sets.newHashSet();
|
||||
// TODO: slow
|
||||
Set<VariableDescriptor> variables = resolveFieldGroup(owner, psiClass, staticMembers);
|
||||
for (VariableDescriptor variable : variables) {
|
||||
if (variable.getName().equals(fieldName)) {
|
||||
r.add(variable);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
|
||||
|
||||
NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName);
|
||||
if (namedMembers == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
resolveNamedGroupProperties(owner, staticMembers, namedMembers, fieldName);
|
||||
|
||||
return namedMembers.propertyDescriptors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
|
||||
|
||||
ResolverScopeData scopeData;
|
||||
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;
|
||||
}
|
||||
|
||||
ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
|
||||
|
||||
Set<VariableDescriptor> descriptors = Sets.newHashSet();
|
||||
Map<PropertyKey, MembersForProperty> membersForProperties = getMembersForProperties(psiClass, staticMembers, scopeData.kotlin);
|
||||
for (Map.Entry<PropertyKey, MembersForProperty> entry : membersForProperties.entrySet()) {
|
||||
//VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field);
|
||||
//if (variableDescriptor != null) {
|
||||
// return variableDescriptor;
|
||||
//}
|
||||
String propertyName = entry.getKey().name;
|
||||
PsiType propertyType = entry.getValue().type;
|
||||
PsiType receiverType = entry.getValue().receiverType;
|
||||
MembersForProperty members = entry.getValue();
|
||||
Map<String, NamedMembers> membersForProperties = scopeData.namedMembersMap;
|
||||
for (Map.Entry<String, NamedMembers> entry : membersForProperties.entrySet()) {
|
||||
NamedMembers namedMembers = entry.getValue();
|
||||
if (namedMembers.propertyAccessors == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String propertyName = entry.getKey();
|
||||
|
||||
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;
|
||||
if (members.setter == null && members.getter == null) {
|
||||
isFinal = false;
|
||||
} else if (members.getter != null) {
|
||||
isFinal = members.getter.isFinal();
|
||||
isFinal = members.getter.getMember().isFinal();
|
||||
} else if (members.setter != null) {
|
||||
isFinal = members.setter.isFinal();
|
||||
isFinal = members.setter.getMember().isFinal();
|
||||
} else {
|
||||
isFinal = false;
|
||||
}
|
||||
|
||||
PsiMemberWrapper anyMember;
|
||||
PropertyAccessorData anyMember;
|
||||
if (members.getter != null) {
|
||||
anyMember = members.getter;
|
||||
} else if (members.field != null) {
|
||||
@@ -1036,10 +921,10 @@ public class JavaDescriptorResolver {
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
boolean isVar;
|
||||
if (members.getter == null && members.setter == null) {
|
||||
isVar = true;
|
||||
isVar = !members.field.getMember().isFinal();
|
||||
} else {
|
||||
isVar = members.setter != null;
|
||||
}
|
||||
@@ -1048,11 +933,11 @@ public class JavaDescriptorResolver {
|
||||
owner,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
|
||||
resolveVisibilityFromPsiModifiers(anyMember.psiMember),
|
||||
resolveVisibilityFromPsiModifiers(anyMember.getMember().psiMember),
|
||||
isVar,
|
||||
false,
|
||||
propertyName);
|
||||
|
||||
|
||||
PropertyGetterDescriptor getterDescriptor = null;
|
||||
PropertySetterDescriptor setterDescriptor = null;
|
||||
if (members.getter != null) {
|
||||
@@ -1061,89 +946,124 @@ public class JavaDescriptorResolver {
|
||||
if (members.setter != null) {
|
||||
setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
|
||||
}
|
||||
|
||||
propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
|
||||
|
||||
final List<TypeParameterDescriptor> classTypeParameters;
|
||||
if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) {
|
||||
classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters();
|
||||
} else {
|
||||
classTypeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
||||
}
|
||||
TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters);
|
||||
propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
||||
|
||||
if (members.setter != null) {
|
||||
// call ugly code with side effects
|
||||
typeParameters = resolveMethodTypeParameters(members.setter, propertyDescriptor.getSetter(), typeVariableResolver);
|
||||
PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember();
|
||||
|
||||
if (anyMember == members.setter) {
|
||||
typeParameters = resolveMethodTypeParameters(method, setterDescriptor, typeVariableResolver);
|
||||
}
|
||||
}
|
||||
if (members.getter != null) {
|
||||
// call ugly code with side effects
|
||||
typeParameters = resolveMethodTypeParameters(members.getter, propertyDescriptor.getGetter(), typeVariableResolver);
|
||||
PsiMethodWrapper method = (PsiMethodWrapper) members.getter.getMember();
|
||||
|
||||
if (anyMember == members.getter) {
|
||||
typeParameters = resolveMethodTypeParameters(method, getterDescriptor, typeVariableResolver);
|
||||
}
|
||||
}
|
||||
|
||||
JetType receiverJetType;
|
||||
if (receiverType == null) {
|
||||
receiverJetType = null;
|
||||
List<TypeParameterDescriptor> typeParametersForReceiver = new ArrayList<TypeParameterDescriptor>();
|
||||
typeParametersForReceiver.addAll(classTypeParameters);
|
||||
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 {
|
||||
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(
|
||||
type,
|
||||
propertyType,
|
||||
typeParameters,
|
||||
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
|
||||
receiverJetType
|
||||
);
|
||||
receiverType
|
||||
);
|
||||
if (getterDescriptor != null) {
|
||||
getterDescriptor.initialize(type);
|
||||
getterDescriptor.initialize(propertyType);
|
||||
}
|
||||
if (setterDescriptor != null) {
|
||||
// TODO: initialize
|
||||
}
|
||||
|
||||
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.getMember().psiMember, propertyDescriptor);
|
||||
|
||||
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor);
|
||||
//fieldDescriptorCache.put(field, propertyDescriptor);
|
||||
descriptors.add(propertyDescriptor);
|
||||
r.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
|
||||
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);
|
||||
for (HierarchicalMethodSignature signature: signatures) {
|
||||
if (!methodName.equals(signature.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
resolveNamedGroupFunctions(owner, psiClass, typeSubstitutor, staticMembers, namedMembers, methodName);
|
||||
|
||||
return namedMembers.functionDescriptors;
|
||||
}
|
||||
|
||||
public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) {
|
||||
@@ -1178,16 +1098,15 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod psiMethod) {
|
||||
PsiMethodWrapper method = new PsiMethodWrapper(psiMethod);
|
||||
public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethodWrapper method) {
|
||||
|
||||
PsiType returnType = psiMethod.getReturnType();
|
||||
PsiType returnType = method.getReturnType();
|
||||
if (returnType == null) {
|
||||
return null;
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = methodDescriptorCache.get(psiMethod);
|
||||
FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method.getPsiMethod());
|
||||
if (functionDescriptor != null) {
|
||||
if (psiMethod.getContainingClass() != psiClass) {
|
||||
if (method.getPsiMethod().getContainingClass() != psiClass) {
|
||||
functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses);
|
||||
}
|
||||
return functionDescriptor;
|
||||
@@ -1238,11 +1157,11 @@ public class JavaDescriptorResolver {
|
||||
DeclarationDescriptor classDescriptor;
|
||||
final List<TypeParameterDescriptor> classTypeParameters;
|
||||
if (method.isStatic()) {
|
||||
classDescriptor = resolveNamespace(psiMethod.getContainingClass());
|
||||
classDescriptor = resolveNamespace(method.getPsiMethod().getContainingClass());
|
||||
classTypeParameters = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
ClassDescriptor classClassDescriptor = resolveClass(psiMethod.getContainingClass());
|
||||
ClassDescriptor classClassDescriptor = resolveClass(method.getPsiMethod().getContainingClass());
|
||||
classDescriptor = classClassDescriptor;
|
||||
classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters();
|
||||
}
|
||||
@@ -1252,14 +1171,14 @@ public class JavaDescriptorResolver {
|
||||
NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl(
|
||||
owner,
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
psiMethod.getName()
|
||||
method.getName()
|
||||
);
|
||||
methodDescriptorCache.put(psiMethod, functionDescriptorImpl);
|
||||
methodDescriptorCache.put(method.getPsiMethod(), functionDescriptorImpl);
|
||||
|
||||
// TODO: add outer classes
|
||||
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 {
|
||||
|
||||
@@ -1288,12 +1207,12 @@ public class JavaDescriptorResolver {
|
||||
methodTypeParameters,
|
||||
valueParameterDescriptors.descriptors,
|
||||
makeReturnType(returnType, method, new MethodTypeVariableResolver()),
|
||||
Modality.convertFromFlags(psiMethod.hasModifierProperty(PsiModifier.ABSTRACT), !psiMethod.hasModifierProperty(PsiModifier.FINAL)),
|
||||
resolveVisibilityFromPsiModifiers(psiMethod)
|
||||
Modality.convertFromFlags(method.getPsiMethod().hasModifierProperty(PsiModifier.ABSTRACT), !method.isFinal()),
|
||||
resolveVisibilityFromPsiModifiers(method.getPsiMethod())
|
||||
);
|
||||
semanticServices.getTrace().record(BindingContext.FUNCTION, psiMethod, functionDescriptorImpl);
|
||||
semanticServices.getTrace().record(BindingContext.FUNCTION, method.getPsiMethod(), functionDescriptorImpl);
|
||||
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
|
||||
if (psiMethod.getContainingClass() != psiClass) {
|
||||
if (method.getPsiMethod().getContainingClass() != psiClass) {
|
||||
substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses);
|
||||
}
|
||||
return substitutedFunctionDescriptor;
|
||||
@@ -1301,7 +1220,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
private List<TypeParameterDescriptor> resolveMethodTypeParameters(
|
||||
@NotNull PsiMethodWrapper method,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull DeclarationDescriptor functionDescriptor,
|
||||
@NotNull TypeVariableResolver classTypeVariableResolver) {
|
||||
if (method.getJetMethod().typeParameters().length() > 0) {
|
||||
List<TypeParameterDescriptor> r = resolveMethodTypeParametersFromJetSignature(
|
||||
@@ -1319,7 +1238,7 @@ public class JavaDescriptorResolver {
|
||||
* @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, MutableClassDescriptorLite)
|
||||
*/
|
||||
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>();
|
||||
|
||||
@@ -1400,7 +1319,7 @@ public class JavaDescriptorResolver {
|
||||
ownerOwner = 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);
|
||||
}
|
||||
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.jet.lang.JetSemanticServices;
|
||||
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.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
@@ -46,6 +47,14 @@ public class JavaSemanticServices {
|
||||
|
||||
@Nullable
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -108,11 +108,14 @@ public class JavaTypeTransformer {
|
||||
for (TypeParameterDescriptor parameter : parameters) {
|
||||
arguments.add(TypeUtils.makeStarProjection(parameter));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
List<TypeParameterDescriptor> parameters = descriptor.getTypeConstructor().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];
|
||||
TypeParameterDescriptor typeParameterDescriptor = descriptor.getTypeConstructor().getParameters().get(i);
|
||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||
|
||||
arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor));
|
||||
}
|
||||
}
|
||||
@@ -187,7 +190,6 @@ public class JavaTypeTransformer {
|
||||
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
||||
classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType));
|
||||
}
|
||||
//classDescriptorMap.put("java.lang.Object", standardLibrary.get
|
||||
classDescriptorMap.put("java.lang.String", standardLibrary.getString());
|
||||
}
|
||||
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.Variance;
|
||||
import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
|
||||
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
|
||||
import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
@@ -75,6 +78,26 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
|
||||
|
||||
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) {
|
||||
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
|
||||
}
|
||||
@@ -86,22 +109,22 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
|
||||
this.typeArguments = new ArrayList<TypeProjection>();
|
||||
}
|
||||
|
||||
private static Variance parseVariance(char wildcard) {
|
||||
switch (wildcard) {
|
||||
case '=': return Variance.INVARIANT;
|
||||
case '+': return Variance.OUT_VARIANCE;
|
||||
case '-': return Variance.IN_VARIANCE;
|
||||
private static Variance parseVariance(JetSignatureVariance variance) {
|
||||
switch (variance) {
|
||||
case INVARIANT: return Variance.INVARIANT;
|
||||
case OUT: return Variance.OUT_VARIANCE;
|
||||
case IN: return Variance.IN_VARIANCE;
|
||||
default: throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
|
||||
public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance variance) {
|
||||
return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) {
|
||||
|
||||
@Override
|
||||
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(),
|
||||
nullable,
|
||||
typeArguments,
|
||||
ErrorUtils.getErrorScope());
|
||||
classDescriptor.getMemberScope(typeArguments));
|
||||
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;
|
||||
|
||||
import com.intellij.psi.PsiField;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -10,4 +12,12 @@ public class PsiFieldWrapper extends PsiMemberWrapper {
|
||||
public PsiFieldWrapper(@NotNull PsiMember 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
|
||||
*/
|
||||
public class PsiMemberWrapper {
|
||||
public abstract class PsiMemberWrapper {
|
||||
|
||||
@NotNull
|
||||
protected final PsiMember psiMember;
|
||||
@@ -23,7 +23,11 @@ public class PsiMemberWrapper {
|
||||
public boolean isPrivate() {
|
||||
return psiMember.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
}
|
||||
|
||||
|
||||
public boolean isFinal() {
|
||||
return psiMember.hasModifierProperty(PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
public String 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.PsiModifier;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.PsiType;
|
||||
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.JetMethodAnnotation;
|
||||
|
||||
@@ -37,10 +39,6 @@ public class PsiMethodWrapper extends PsiMemberWrapper {
|
||||
return getParameters().get(i);
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return psiMember.hasModifierProperty(PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
private JetMethodAnnotation jetMethod;
|
||||
@NotNull
|
||||
public JetMethodAnnotation getJetMethod() {
|
||||
@@ -59,8 +57,17 @@ public class PsiMethodWrapper extends PsiMemberWrapper {
|
||||
return jetConstructor;
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return psiMember.hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiMethod getPsiMethod() {
|
||||
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.TransientReceiver;
|
||||
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.TypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
@@ -37,6 +38,15 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
||||
private List<TypeParameterDescriptor> typeParemeters;
|
||||
private PropertyGetterDescriptor getter;
|
||||
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(
|
||||
@Nullable PropertyDescriptor original,
|
||||
@@ -243,4 +253,8 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
||||
propertyDescriptor.initialize(newGetter, newSetter);
|
||||
return propertyDescriptor;
|
||||
}
|
||||
|
||||
public static PropertyDescriptor createDummy() {
|
||||
return new PropertyDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
||||
this,
|
||||
annotations,
|
||||
false,
|
||||
"&" + name,
|
||||
name,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
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 actualArgumentCount = arguments.size();
|
||||
if (ErrorUtils.isError(typeConstructor)) {
|
||||
result[0] = new JetTypeImpl(
|
||||
annotations,
|
||||
typeConstructor,
|
||||
nullable,
|
||||
arguments, // TODO : review
|
||||
classDescriptor.getMemberScope(Collections.<TypeProjection>emptyList())
|
||||
);
|
||||
result[0] = ErrorUtils.createErrorType("??");
|
||||
}
|
||||
else {
|
||||
if (actualArgumentCount != expectedArgumentCount) {
|
||||
|
||||
@@ -15,7 +15,13 @@ import java.util.*;
|
||||
public class ErrorUtils {
|
||||
|
||||
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
|
||||
public ClassifierDescriptor getClassifier(@NotNull String name) {
|
||||
@@ -82,7 +88,7 @@ public class ErrorUtils {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private static final ClassDescriptorImpl ERROR_CLASS = new ClassDescriptorImpl(ERROR_MODULE, Collections.<AnnotationDescriptor>emptyList(), "<ERROR CLASS>") {
|
||||
@NotNull
|
||||
@@ -96,6 +102,12 @@ public class ErrorUtils {
|
||||
public Modality getModality() {
|
||||
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()));
|
||||
|
||||
@@ -78,6 +78,7 @@ public class JetStandardLibrary {
|
||||
private EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType;
|
||||
private EnumMap<PrimitiveType, JetType> primitiveTypeToNullableArrayJetType;
|
||||
private Map<JetType, JetType> primitiveJetTypeToJetArrayType;
|
||||
private Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
|
||||
|
||||
private JetStandardLibrary(@NotNull Project project) {
|
||||
// TODO : review
|
||||
@@ -147,6 +148,7 @@ public class JetStandardLibrary {
|
||||
primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
|
||||
primitiveTypeToNullableArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
|
||||
primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
|
||||
jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>();
|
||||
|
||||
for (PrimitiveType primitive : PrimitiveType.values()) {
|
||||
makePrimitive(primitive);
|
||||
@@ -167,6 +169,7 @@ public class JetStandardLibrary {
|
||||
primitiveTypeToArrayJetType.put(primitiveType, arrayType);
|
||||
primitiveTypeToNullableArrayJetType.put(primitiveType, TypeUtils.makeNullable(arrayType));
|
||||
primitiveJetTypeToJetArrayType.put(type, arrayType);
|
||||
jetArrayTypeToPrimitiveJetType.put(arrayType, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -334,6 +337,22 @@ public class JetStandardLibrary {
|
||||
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
|
||||
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) {
|
||||
super(annotations);
|
||||
|
||||
if (memberScope instanceof ErrorUtils.ErrorScope) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
this.constructor = constructor;
|
||||
this.nullable = nullable;
|
||||
this.arguments = arguments;
|
||||
|
||||
@@ -100,6 +100,9 @@ public class TypeUtils {
|
||||
if (type.isNullable() == nullable) {
|
||||
return type;
|
||||
}
|
||||
if (ErrorUtils.isErrorType(type)) {
|
||||
return type;
|
||||
}
|
||||
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), nullable, type.getArguments(), type.getMemberScope());
|
||||
}
|
||||
|
||||
@@ -285,6 +288,9 @@ public class TypeUtils {
|
||||
|
||||
@NotNull
|
||||
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());
|
||||
return new JetTypeImpl(
|
||||
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