Merge remote-tracking branch 'origin/master'

This commit is contained in:
svtk
2012-01-18 13:31:52 +04:00
181 changed files with 2587 additions and 597 deletions
+1 -1
View File
@@ -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>
+271
View File
@@ -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="&lt;a href=&quot;http://jetbrains.com/kotlin&quot;&gt;"/>
<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="&lt;a href=&quot;http://jetbrains.com/kotlin&quot;&gt;"/>
</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
+3
View File
@@ -0,0 +1,3 @@
fun main(args : Array<String>) {
System.out?.println("Hello, world!")
}
+7
View File
@@ -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]}!")
}
+4
View File
@@ -0,0 +1,4 @@
fun main(args : Array<String>) {
for (name in args)
System.out?.println("Hello, $name!")
}
+9
View File
@@ -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"
})
}
+9
View File
@@ -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)
}
+172
View File
@@ -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
}
+231
View File
@@ -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
}
+8 -5
View File
@@ -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);
@@ -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
@@ -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);
@@ -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;
}
}
@@ -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);
}
@@ -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;
@@ -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);
}
}
@@ -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();
}
}
@@ -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();
}
@@ -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();
}
}
@@ -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