Merge pull request #1398 from SerVB/kotlin-netbeans-to-merge
Kotlin Plugin Donation
diff --git a/contrib/kotlin/.gitignore b/contrib/kotlin/.gitignore
new file mode 100644
index 0000000..f6b5750
--- /dev/null
+++ b/contrib/kotlin/.gitignore
@@ -0,0 +1,5 @@
+/target/
+/src/test/resources/projForTest/nbproject/private/
+nb-configuration.xml
+nbactions.xml
+.DS_Store
diff --git a/contrib/kotlin/README.md b/contrib/kotlin/README.md
new file mode 100644
index 0000000..e78a172
--- /dev/null
+++ b/contrib/kotlin/README.md
@@ -0,0 +1,41 @@
+[![JetBrains team project](https://jb.gg/badges/obsolete.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
+[![TeamCity (simple build status)](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/Kotlin_NetBeansPlugin.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_NetBeansPlugin&branch_Kotlin=%3Cdefault%3E&tab=buildTypeStatusDiv)
+[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
+
+# Kotlin plugin for NetBeans IDE
+
+**NOTE**: This plugin is no longer actively developed. See https://github.com/JetBrains/kotlin-netbeans/issues/122 for more information.
+
+## Installing Kotlin plugin
+
+### NetBeans Update Center
+
+The plugin could be installed via NetBeans Update Center.
+
+### Manual installation
+
+1. Download the latest release: [0.2.0.1](https://github.com/JetBrains/kotlin-netbeans/releases/tag/v0.2.0.1)
+2. Launch NetBeans IDE
+3. Choose **Tools** and then **Plugins** from the main menu
+4. Switch to **Downloaded** tab
+5. On the **Downloaded** tab click **Add Plugins...** button
+6. In the file chooser, navigate to the folder with downloaded plugin. Select the NBM file and click OK. The plugin will show up in the list of plugins to be installed.
+7. Click **Install** button in the Plugins dialog
+8. Complete the installation wizard by clicking **Next**, agreeing to the license terms and clicking **Install** button.
+
+
+## Plugin feature set
+
+1. Syntax highlighting
+2. Semantics highlighting
+3. Diagnostics
+4. Code completion
+5. Navigation in Source Code
+6. Quick fixes
+7. Intentions and Inspections
+8. Occurrences finder
+9. Code folding
+10. Unit testing support
+11. Ant, Maven and Gradle support
+12. Navigation by Kotlin class name
+13. Debugging support
diff --git a/contrib/kotlin/license.txt b/contrib/kotlin/license.txt
new file mode 100644
index 0000000..a4f8da3
--- /dev/null
+++ b/contrib/kotlin/license.txt
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
diff --git a/contrib/kotlin/licenseheader.txt b/contrib/kotlin/licenseheader.txt
new file mode 100644
index 0000000..3aa8850
--- /dev/null
+++ b/contrib/kotlin/licenseheader.txt
@@ -0,0 +1,19 @@
+<#if licenseFirst??>
+${licenseFirst}
+</#if>
+${licensePrefix}Copyright 2000-${date?date?string("yyyy")} JetBrains s.r.o.
+${licensePrefix?replace(" +$", "", "r")}
+${licensePrefix}Licensed under the Apache License, Version 2.0 (the "License");
+${licensePrefix}you may not use this file except in compliance with the License.
+${licensePrefix}You may obtain a copy of the License at
+${licensePrefix?replace(" +$", "", "r")}
+${licensePrefix} http://www.apache.org/licenses/LICENSE-2.0
+${licensePrefix?replace(" +$", "", "r")}
+${licensePrefix}Unless required by applicable law or agreed to in writing, software
+${licensePrefix}distributed under the License is distributed on an "AS IS" BASIS,
+${licensePrefix}WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+${licensePrefix}See the License for the specific language governing permissions and
+${licensePrefix}limitations under the License.
+<#if licenseLast??>
+${licenseLast}
+</#if>
\ No newline at end of file
diff --git a/contrib/kotlin/pom.xml b/contrib/kotlin/pom.xml
new file mode 100644
index 0000000..c9177e8
--- /dev/null
+++ b/contrib/kotlin/pom.xml
@@ -0,0 +1,789 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>Kotlin</groupId>
+ <artifactId>kotlin.netbeans.plugin</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <packaging>nbm</packaging>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <netbeans.version>RELEASE82</netbeans.version>
+ <kotlin.version>1.1.1</kotlin.version>
+ </properties>
+ <name>Kotlin</name>
+ <description url="https://kotlinlang.org/">Kotlin language support</description>
+ <organization>
+ <name>JetBrains</name>
+ <url>https://www.jetbrains.com/</url>
+ </organization>
+ <developers>
+ <developer>
+ <name>Mikhail Glukhikh</name>
+ <email>mikhail.glukhikh [at] jetbrains.com</email>
+ </developer>
+ <developer>
+ <name>Alexander Baratynskiy</name>
+ <email>alexander.baratynskiy [at] jetbrains.com</email>
+ </developer>
+ </developers>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.5.2</version>
+ <executions>
+ <execution>
+ <id>inst1</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/kotlin-ide-common.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-ide-common</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inst2</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/openapi-formatter.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>openapi-formatter</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inst3</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/kotlin-formatter.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-formatter</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inst4</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/idea-formatter.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>idea-formatter</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inst5</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/intellij-core.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>intellij-core</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inst6</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/kotlin-converter.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-converter</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inst7</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <file>${project.basedir}/lib/asm-all.jar</file>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>asm</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <version>${kotlin.version}</version>
+ <executions>
+ <execution>
+ <id>compile</id>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <phase>process-test-sources</phase>
+ <goals>
+ <goal>test-compile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>nbm-maven-plugin</artifactId>
+ <version>4.1</version>
+ <extensions>true</extensions>
+ <configuration>
+ <licenseFile>license.txt</licenseFile>
+ <licenseName>Apache License, Version 2.0</licenseName>
+ <verifyRuntime>warn</verifyRuntime>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.3</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <useDefaultManifestFile>true</useDefaultManifestFile>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.15</version>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>netbeans-modules</id>
+ <name>Repository hosting NetBeans modules</name>
+ <url>https://bits.netbeans.org/nexus/content/groups/netbeans</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>netbeans-api-artifacts</id>
+ <name>Repository hosting netbeans.org api artifacts</name>
+ <url>https://bits.netbeans.org/maven2/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+
+ </repositories>
+ <dependencies>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-ide-common</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>openapi-formatter</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-formatter</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>idea-formatter</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>intellij-core</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-converter</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>asm</artifactId>
+ <version>1.0</version>
+ <type>jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-compiler</artifactId>
+ <version>${kotlin.version}</version>
+ <type>jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-maven</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-maven-embedder</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-parsing-api</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-dialogs</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-spi-editor-hints</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-core-multiview</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-lexer</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-csl-api</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-editor-errorstripe</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-project-ant</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-projectuiapi</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-java-classpath</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-projectapi</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-filesystems</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-util-ui</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-util-lookup</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-util</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-apache-tools-ant-module</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-loaders</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-awt</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-nodes</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-indent</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-projectuiapi-base</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.external</groupId>
+ <artifactId>asm-all-5.0.1</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-windows</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-java</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-execution</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-completion</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-java-source-base</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-libs-javacapi</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.external</groupId>
+ <artifactId>nb-javac-api</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-text</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-bracesmatching</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-modules</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-java-project-ui</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-fold</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-lib2</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-mimelookup</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-templates</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-java-preprocessorbridge</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor-lib</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-java-sourceui</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-progress</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-progress-nb</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-java-j2seproject</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-java-project</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-java-api-common</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-java-platform</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-refactoring-api</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-java-editor</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-jumpto</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-spi-quicksearch</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-debugger</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-debugger-jpda</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-spi-viewmodel</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-debugger-jpda</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-debugger-jpda-projectsui</artifactId>
+ <version>${netbeans.version}</version>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-spi-debugger-ui</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-debugger-jpda-projects</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-editor</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-parsing-indexing</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-maven-indexer</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-project-libraries</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-maven-model</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-api-annotations-common</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-xml-xam</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-csl-types</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>14.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-refactoring-java</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-openide-io</artifactId>
+ <version>${netbeans.version}</version>
+ </dependency>
+ <!-- TEST DEPENDENCIES -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-junit</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-junit-ant</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-junit-ant-ui</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-junit-ui</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-junitlib</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-java</artifactId>
+ <scope>test</scope>
+ <version>2.44.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.opera</groupId>
+ <artifactId>operadriver</artifactId>
+ <scope>test</scope>
+ <version>1.5</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-remote-driver</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.modules</groupId>
+ <artifactId>org-netbeans-modules-projectapi-nb</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ <version>2.7.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>xalan</groupId>
+ <artifactId>serializer</artifactId>
+ <version>2.7.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.4.01</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.external</groupId>
+ <artifactId>xerces-2.8.0</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-apache-xml-resolver</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.external</groupId>
+ <artifactId>resolver-1.2</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.netbeans.api</groupId>
+ <artifactId>org-netbeans-modules-nbjunit</artifactId>
+ <version>${netbeans.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/contrib/kotlin/src/main/java/com/intellij/codeInsight/CodeInsightBundle.java b/contrib/kotlin/src/main/java/com/intellij/codeInsight/CodeInsightBundle.java
new file mode 100644
index 0000000..21d3408
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/codeInsight/CodeInsightBundle.java
@@ -0,0 +1,25 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.codeInsight;
+
+public class CodeInsightBundle {
+ public static String message(String key, Object... params) {
+ return key;
+ }
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/contrib/kotlin/src/main/java/com/intellij/codeInsight/actions/ReformatCodeProcessor.java
new file mode 100644
index 0000000..a7339df
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/codeInsight/actions/ReformatCodeProcessor.java
@@ -0,0 +1,23 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.codeInsight.actions;
+
+public class ReformatCodeProcessor {
+ public static final String COMMAND_NAME = "dummy";
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/codeInsight/generation/GenerateEqualsHelper.java b/contrib/kotlin/src/main/java/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
new file mode 100644
index 0000000..288bbf3
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/codeInsight/generation/GenerateEqualsHelper.java
@@ -0,0 +1,38 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.codeInsight.generation;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import com.intellij.psi.PsiTypeParameter;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.MethodSignatureUtil;
+
+// Temp workaround for bad j2k classes politics
+public class GenerateEqualsHelper {
+ public static MethodSignature getEqualsSignature(Project project, GlobalSearchScope scope) {
+ final PsiClassType javaLangObject = PsiType.getJavaLangObject(PsiManager.getInstance(project), scope);
+ return MethodSignatureUtil.createMethodSignature(
+ "equals", new PsiType[]{javaLangObject}, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
+ }
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/formatting/DependantSpacingImpl.java b/contrib/kotlin/src/main/java/com/intellij/formatting/DependantSpacingImpl.java
new file mode 100644
index 0000000..263a5c5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/formatting/DependantSpacingImpl.java
@@ -0,0 +1,127 @@
+package com.intellij.formatting;
+
+import java.util.List;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.intellij.formatting.engine.BlockRangesMap;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+
+/**
+ * Extends {@link SpacingImpl} in order to add notion of dependency range.
+ * <p/>
+ * <code>'Dependency'</code> here affect {@link #getMinLineFeeds()
+ * minLineFieeds} property value. See property contract for more details.
+ */
+public class DependantSpacingImpl extends SpacingImpl {
+ private static final int DEPENDENCE_CONTAINS_LF_MASK = 0x10;
+ private static final int DEPENDENT_REGION_LF_CHANGED_MASK = 0x20;
+
+ @NotNull
+ private final List<TextRange> myDependentRegionRanges;
+ @NotNull
+ private final DependentSpacingRule myRule;
+
+ public DependantSpacingImpl(final int minSpaces, final int maxSpaces, @NotNull TextRange dependency,
+ final boolean keepLineBreaks, final int keepBlankLines, @NotNull DependentSpacingRule rule) {
+ super(minSpaces, maxSpaces, 0, false, false, keepLineBreaks, keepBlankLines, false, 0);
+ myDependentRegionRanges = ContainerUtil.newSmartList(dependency);
+ myRule = rule;
+ }
+
+ public DependantSpacingImpl(final int minSpaces, final int maxSpaces, @NotNull List<TextRange> dependencyRanges,
+ final boolean keepLineBreaks, final int keepBlankLines, @NotNull DependentSpacingRule rule) {
+ super(minSpaces, maxSpaces, 0, false, false, keepLineBreaks, keepBlankLines, false, 0);
+ myDependentRegionRanges = dependencyRanges;
+ myRule = rule;
+ }
+
+ /**
+ * @return <code>1</code> if dependency has line feeds; <code>0</code>
+ * otherwise
+ */
+ @Override
+ public int getMinLineFeeds() {
+ if (!isTriggered()) {
+ return super.getMinLineFeeds();
+ }
+
+ if (myRule.hasData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS)) {
+ return myRule.getData(DependentSpacingRule.Anchor.MIN_LINE_FEEDS);
+ }
+
+ if (myRule.hasData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS)) {
+ return myRule.getData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS);
+ }
+ return super.getMinLineFeeds();
+ }
+
+ @Override
+ public int getKeepBlankLines() {
+ if (!isTriggered() || !myRule.hasData(DependentSpacingRule.Anchor.MAX_LINE_FEEDS)) {
+ return super.getKeepBlankLines();
+ }
+
+ return 0;
+ }
+
+ @Override
+ public void refresh(BlockRangesMap helper) {
+ if (isDependentRegionLinefeedStatusChanged()) {
+ return;
+ }
+
+ boolean atLeastOneDependencyRangeContainsLf = false;
+ for (TextRange dependency : myDependentRegionRanges) {
+ atLeastOneDependencyRangeContainsLf |= helper.containsLineFeeds(dependency);
+ }
+
+ if (atLeastOneDependencyRangeContainsLf)
+ myFlags |= DEPENDENCE_CONTAINS_LF_MASK;
+ else
+ myFlags &= ~DEPENDENCE_CONTAINS_LF_MASK;
+ }
+
+ @NotNull
+ public List<TextRange> getDependentRegionRanges() {
+ return myDependentRegionRanges;
+ }
+
+ /**
+ * Allows to answer whether 'contains line feed' status has been changed for
+ * the target dependent region during formatting.
+ *
+ * @return <code>true</code> if target 'contains line feed' status has been
+ * changed for the target dependent region during formatting;
+ * <code>false</code> otherwise
+ */
+ public final boolean isDependentRegionLinefeedStatusChanged() {
+ return (myFlags & DEPENDENT_REGION_LF_CHANGED_MASK) != 0;
+ }
+
+ /**
+ * Allows to set {@link #isDependentRegionLinefeedStatusChanged() 'dependent
+ * region changed'} property.
+ */
+ public final void setDependentRegionLinefeedStatusChanged() {
+ myFlags |= DEPENDENT_REGION_LF_CHANGED_MASK;
+ if (getMinLineFeeds() <= 0)
+ myFlags |= DEPENDENCE_CONTAINS_LF_MASK;
+ else
+ myFlags &= ~DEPENDENCE_CONTAINS_LF_MASK;
+ }
+
+ @Override
+ public String toString() {
+ String dependencies = StringUtil.join(myDependentRegionRanges, ", ");
+ return "<DependantSpacing: minSpaces=" + getMinSpaces() + " maxSpaces=" + getMaxSpaces() + " minLineFeeds="
+ + getMinLineFeeds() + " dep=" + dependencies + ">";
+ }
+
+ private boolean isTriggered() {
+ return myRule.getTrigger() == DependentSpacingRule.Trigger.HAS_LINE_FEEDS
+ ^ (myFlags & DEPENDENCE_CONTAINS_LF_MASK) == 0;
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/com/intellij/formatting/KotlinLanguageCodeStyleSettingsProvider.java b/contrib/kotlin/src/main/java/com/intellij/formatting/KotlinLanguageCodeStyleSettingsProvider.java
new file mode 100644
index 0000000..1258cc9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/formatting/KotlinLanguageCodeStyleSettingsProvider.java
@@ -0,0 +1,62 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.formatting;
+
+import com.intellij.application.options.IndentOptionsEditor;
+import com.intellij.lang.Language;
+import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
+import org.jetbrains.kotlin.idea.KotlinLanguage;
+
+public class KotlinLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider {
+
+ @Override
+ public Language getLanguage() {
+ return KotlinLanguage.INSTANCE;
+ }
+
+ @Override
+ public String getCodeSample(SettingsType settingsType) {
+ return "";
+ }
+
+ @Override
+ public String getLanguageName() {
+ return KotlinLanguage.NAME;
+ }
+
+ @Override
+ public void customizeSettings(CodeStyleSettingsCustomizable consumer, SettingsType settingsType) {
+ }
+
+ @Override
+ public IndentOptionsEditor getIndentOptionsEditor(){
+ return null;
+ }
+
+ @Override
+ public CommonCodeStyleSettings getDefaultCommonSettings() {
+ CommonCodeStyleSettings commonSettings =
+ new CommonCodeStyleSettings(getLanguage());
+ commonSettings.initIndentOptions();
+ return commonSettings;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/formatting/KotlinSettingsProvider.java b/contrib/kotlin/src/main/java/com/intellij/formatting/KotlinSettingsProvider.java
new file mode 100644
index 0000000..e08f0f2
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/formatting/KotlinSettingsProvider.java
@@ -0,0 +1,51 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.formatting;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
+import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
+import org.jetbrains.kotlin.idea.KotlinLanguage;
+import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings;
+
+public class KotlinSettingsProvider extends CodeStyleSettingsProvider {
+
+ @Override
+ public String getConfigurableDisplayName() {
+ return KotlinLanguage.NAME;
+ }
+
+ @Override
+ public Language getLanguage() {
+ return KotlinLanguage.INSTANCE;
+ }
+
+ @Override
+ public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
+ return new KotlinCodeStyleSettings(settings);
+ }
+
+ @Override
+ public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/openapi/editor/Editor.java b/contrib/kotlin/src/main/java/com/intellij/openapi/editor/Editor.java
new file mode 100644
index 0000000..9789a38
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/openapi/editor/Editor.java
@@ -0,0 +1,23 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.openapi.editor;
+
+public class Editor {
+
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/openapi/extensions/ExtensionException.java b/contrib/kotlin/src/main/java/com/intellij/openapi/extensions/ExtensionException.java
new file mode 100644
index 0000000..6de885f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/openapi/extensions/ExtensionException.java
@@ -0,0 +1,31 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.openapi.extensions;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class ExtensionException extends RuntimeException {
+
+ public ExtensionException(Class extensionClass) {
+ super(extensionClass.getCanonicalName());
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/openapi/fileTypes/StdFileTypes.java b/contrib/kotlin/src/main/java/com/intellij/openapi/fileTypes/StdFileTypes.java
new file mode 100644
index 0000000..20bb4db
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/openapi/fileTypes/StdFileTypes.java
@@ -0,0 +1,23 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.openapi.fileTypes;
+
+public class StdFileTypes {
+ public static final LanguageFileType JAVA = null;
+}
diff --git a/contrib/kotlin/src/main/java/com/intellij/util/SequentialModalProgressTask.java b/contrib/kotlin/src/main/java/com/intellij/util/SequentialModalProgressTask.java
new file mode 100644
index 0000000..95ade32
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/util/SequentialModalProgressTask.java
@@ -0,0 +1,120 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.util;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+
+public class SequentialModalProgressTask extends Task.Modal {
+ private static final Logger LOG = Logger.getInstance("#" + SequentialModalProgressTask.class.getName());
+
+ private static final long DEFAULT_MIN_ITERATION_MIN_TIME = 500;
+
+ /**
+ * We want to perform the task by big chunks at EDT. However, there is a
+ * possible case that particular task iteration is executed in short amount
+ * of time. Hence, we may want to execute more than one chunk during single
+ * EDT iteration. This field holds min amount of time (in milliseconds) to
+ * spend to performing the task.
+ */
+ private long myMinIterationTime = DEFAULT_MIN_ITERATION_MIN_TIME;
+
+ private final String myTitle;
+
+ private ProgressIndicator myIndicator;
+ private SequentialTask myTask;
+
+ public SequentialModalProgressTask(@Nullable Project project, @NotNull String title) {
+ this(project, title, true);
+ }
+
+ public SequentialModalProgressTask(@Nullable Project project, @NotNull String title, boolean canBeCancelled) {
+ super(project, title, canBeCancelled);
+ myTitle = title;
+ }
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ try {
+ doRun(indicator);
+ } catch (Exception e) {
+ LOG.info("Unexpected exception occurred during processing sequential task '" + myTitle + "'", e);
+ } finally {
+ indicator.stop();
+ }
+ }
+
+ public void doRun(@NotNull ProgressIndicator indicator) throws InvocationTargetException, InterruptedException {
+ final SequentialTask task = myTask;
+ if (task == null) {
+ return;
+ }
+
+ myIndicator = indicator;
+ prepare(task);
+
+ // We need to sync background thread and EDT here in order to avoid
+ // situation when event queue is full of processing requests.
+ while (!task.isDone()) {
+ if (indicator.isCanceled()) {
+ task.stop();
+ break;
+ }
+ long start = System.currentTimeMillis();
+ try {
+ while (!task.isDone() && System.currentTimeMillis() - start < myMinIterationTime) {
+ task.iteration();
+ }
+ } catch (RuntimeException e) {
+ task.stop();
+ throw e;
+ }
+ }
+ }
+
+ public void setMinIterationTime(long minIterationTime) {
+ myMinIterationTime = minIterationTime;
+ }
+
+ public void setTask(@Nullable SequentialTask task) {
+ myTask = task;
+ }
+
+ public ProgressIndicator getIndicator() {
+ return myIndicator;
+ }
+
+ /**
+ * Executes preliminary jobs prior to the target sequential task processing
+ * ({@link SequentialTask#prepare()} by default).
+ *
+ * @param task
+ * task to be executed
+ */
+ protected void prepare(@NotNull SequentialTask task) {
+ task.prepare();
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/com/intellij/util/SequentialTask.java b/contrib/kotlin/src/main/java/com/intellij/util/SequentialTask.java
new file mode 100644
index 0000000..3830fec
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/util/SequentialTask.java
@@ -0,0 +1,46 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.util;
+
+public interface SequentialTask {
+
+ /**
+ * Callback method that is assumed to be called before the processing.
+ */
+ void prepare();
+
+ /**
+ * @return <code>true</code> if the processing is complete;
+ * <code>false</code> otherwise
+ */
+ boolean isDone();
+
+ /**
+ * Asks current task to perform one more processing iteration.
+ *
+ * @return <code>true</code> if the processing is done; <code>false</code>
+ * otherwise
+ */
+ boolean iteration();
+
+ /**
+ * Asks current task to stop the processing (if any).
+ */
+ void stop();
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/com/intellij/util/containers/MultiMap.java b/contrib/kotlin/src/main/java/com/intellij/util/containers/MultiMap.java
new file mode 100644
index 0000000..855feb6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/com/intellij/util/containers/MultiMap.java
@@ -0,0 +1,405 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package com.intellij.util.containers;
+
+import java.io.Serializable;
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import org.jetbrains.kotlin.utils.SmartList;
+
+import gnu.trove.THashMap;
+import gnu.trove.TObjectHashingStrategy;
+
+public class MultiMap<K, V> implements Serializable {
+ public static final MultiMap EMPTY = new EmptyMap();
+ private static final long serialVersionUID = -2632269270151455493L;
+
+ protected final Map<K, Collection<V>> myMap;
+ private Collection<V> values;
+
+ public MultiMap() {
+ myMap = createMap();
+ }
+
+ public MultiMap(@NotNull MultiMap<? extends K, ? extends V> toCopy) {
+ this();
+ putAllValues(toCopy);
+ }
+
+ @NotNull
+ public MultiMap<K, V> copy() {
+ return new MultiMap<K, V>(this);
+ }
+
+ public MultiMap(int initialCapacity, float loadFactor) {
+ myMap = createMap(initialCapacity, loadFactor);
+ }
+
+ @NotNull
+ protected Map<K, Collection<V>> createMap() {
+ return new HashMap<K, Collection<V>>();
+ }
+
+ @NotNull
+ protected Map<K, Collection<V>> createMap(int initialCapacity, float loadFactor) {
+ return new HashMap<K, Collection<V>>(initialCapacity);
+ }
+
+ @NotNull
+ protected Collection<V> createCollection() {
+ return new SmartList<V>();
+ }
+
+ @NotNull
+ protected Collection<V> createEmptyCollection() {
+ return Collections.emptyList();
+ }
+
+ public <Kk extends K, Vv extends V> void putAllValues(@NotNull MultiMap<Kk, Vv> from) {
+ for (Map.Entry<Kk, Collection<Vv>> entry : from.entrySet()) {
+ putValues(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public void putValues(K key, @NotNull Collection<? extends V> values) {
+ Collection<V> list = myMap.get(key);
+ if (list == null) {
+ list = createCollection();
+ myMap.put(key, list);
+ }
+ list.addAll(values);
+ }
+
+ public void putValue(@Nullable K key, V value) {
+ Collection<V> list = myMap.get(key);
+ if (list == null) {
+ list = createCollection();
+ myMap.put(key, list);
+ }
+ list.add(value);
+ }
+
+ @NotNull
+ public Set<Map.Entry<K, Collection<V>>> entrySet() {
+ return myMap.entrySet();
+ }
+
+ public boolean isEmpty() {
+ if (myMap.isEmpty())
+ return true;
+
+ for (Collection<V> valueList : myMap.values()) {
+ if (!valueList.isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean containsKey(K key) {
+ return myMap.containsKey(key);
+ }
+
+ public boolean containsScalarValue(V value) {
+ for (Collection<V> valueList : myMap.values()) {
+ if (valueList.contains(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @NotNull
+ public Collection<V> get(final K key) {
+ final Collection<V> collection = myMap.get(key);
+ return collection == null ? createEmptyCollection() : collection;
+ }
+
+ @NotNull
+ public Collection<V> getModifiable(final K key) {
+ Collection<V> collection = myMap.get(key);
+ if (collection == null) {
+ myMap.put(key, collection = createCollection());
+ }
+ return collection;
+ }
+
+ @NotNull
+ public Set<K> keySet() {
+ return myMap.keySet();
+ }
+
+ public int size() {
+ return myMap.size();
+ }
+
+ public void put(final K key, Collection<V> values) {
+ myMap.put(key, values);
+ }
+
+ /**
+ * @deprecated use {@link #remove(Object, Object)} instead
+ */
+ public void removeValue(K key, V value) {
+ remove(key, value);
+ }
+
+ public boolean remove(final K key, final V value) {
+ final Collection<V> values = myMap.get(key);
+ if (values != null) {
+ boolean removed = values.remove(value);
+ if (values.isEmpty()) {
+ myMap.remove(key);
+ }
+ return removed;
+ }
+ return false;
+ }
+
+ @NotNull
+ public Collection<? extends V> values() {
+ if (values == null) {
+ values = new AbstractCollection<V>() {
+ @NotNull
+ @Override
+ public Iterator<V> iterator() {
+ return new Iterator<V>() {
+
+ private final Iterator<Collection<V>> mapIterator = myMap.values().iterator();
+
+ private Iterator<V> itr = EmptyIterator.getInstance();
+
+ @Override
+ public boolean hasNext() {
+ do {
+ if (itr.hasNext())
+ return true;
+ if (!mapIterator.hasNext())
+ return false;
+ itr = mapIterator.next().iterator();
+ } while (true);
+ }
+
+ @Override
+ public V next() {
+ do {
+ if (itr.hasNext())
+ return itr.next();
+ if (!mapIterator.hasNext())
+ throw new NoSuchElementException();
+ itr = mapIterator.next().iterator();
+ } while (true);
+ }
+
+ @Override
+ public void remove() {
+ itr.remove();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ int res = 0;
+ for (Collection<V> vs : myMap.values()) {
+ res += vs.size();
+ }
+
+ return res;
+ }
+
+ // Don't remove this method!!!
+ @Override
+ public boolean contains(Object o) {
+ for (Collection<V> vs : myMap.values()) {
+ if (vs.contains(o))
+ return true;
+ }
+
+ return false;
+ }
+ };
+ }
+
+ return values;
+ }
+
+ public void clear() {
+ myMap.clear();
+ }
+
+ @Nullable
+ public Collection<V> remove(K key) {
+ return myMap.remove(key);
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> emptyInstance() {
+ @SuppressWarnings("unchecked")
+ final MultiMap<K, V> empty = EMPTY;
+ return empty;
+ }
+
+ /**
+ * Null keys supported.
+ */
+ @NotNull
+ public static <K, V> MultiMap<K, V> create() {
+ return new MultiMap<K, V>();
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> create(@NotNull final TObjectHashingStrategy<K> strategy) {
+ return new MultiMap<K, V>() {
+ @NotNull
+ @Override
+ protected Map<K, Collection<V>> createMap() {
+ return new THashMap<K, Collection<V>>(strategy);
+ }
+ };
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createLinked() {
+ return new LinkedMultiMap<K, V>();
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createLinkedSet() {
+ return new LinkedMultiMap<K, V>() {
+ @NotNull
+ @Override
+ protected Collection<V> createCollection() {
+ return ContainerUtil.newLinkedHashSet();
+ }
+ };
+ }
+
+ @Deprecated
+ @SuppressWarnings("unused")
+ @NotNull
+ /**
+ * @deprecated Use {@link #createSmart()}
+ */
+ public static <K, V> MultiMap<K, V> createSmartList() {
+ return createSmart();
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createSmart() {
+ return new MultiMap<K, V>() {
+ @NotNull
+ @Override
+ protected Map<K, Collection<V>> createMap() {
+ return new THashMap<K, Collection<V>>();
+ }
+ };
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createConcurrentSet() {
+ return new MultiMap<K, V>() {
+ @NotNull
+ @Override
+ protected Collection<V> createCollection() {
+ return ContainerUtil.newConcurrentSet();
+ }
+
+ @NotNull
+ @Override
+ protected Collection<V> createEmptyCollection() {
+ return Collections.emptySet();
+ }
+
+ @NotNull
+ @Override
+ protected Map<K, Collection<V>> createMap() {
+ return ContainerUtil.newConcurrentMap();
+ }
+ };
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createSet() {
+ return new MultiMap<K, V>() {
+ @NotNull
+ @Override
+ protected Collection<V> createCollection() {
+ return new SmartHashSet<V>();
+ }
+
+ @NotNull
+ @Override
+ protected Collection<V> createEmptyCollection() {
+ return Collections.emptySet();
+ }
+
+ @NotNull
+ @Override
+ protected Map<K, Collection<V>> createMap() {
+ return new THashMap<K, Collection<V>>();
+ }
+ };
+ }
+
+ public static <K, V> MultiMap<K, V> create(int initialCapacity, float loadFactor) {
+ return new MultiMap<K, V>(initialCapacity, loadFactor);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (!(o instanceof MultiMap))
+ return false;
+ return myMap.equals(((MultiMap) o).myMap);
+ }
+
+ @Override
+ public int hashCode() {
+ return myMap.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return myMap.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <K, V> MultiMap<K, V> empty() {
+ return EMPTY;
+ }
+
+ private static class EmptyMap extends MultiMap {
+ @NotNull
+ @Override
+ protected Map createMap() {
+ return Collections.emptyMap();
+ }
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/builder/KotlinPsiManager.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/builder/KotlinPsiManager.kt
new file mode 100644
index 0000000..53cfa55
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/builder/KotlinPsiManager.kt
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.builder
+
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.openapi.util.text.StringUtilRt
+import com.intellij.openapi.vfs.CharsetToolkit
+import com.intellij.psi.PsiFileFactory
+import com.intellij.psi.impl.PsiFileFactoryImpl
+import java.io.IOException
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.checkProject
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.getKotlinSources
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.model.KotlinLightVirtualFile
+import org.jetbrains.kotlin.project.KotlinProjectConstants
+import org.jetbrains.kotlin.utils.KotlinMockProject
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.idea.KotlinFileType
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.psi.KtFile
+import org.netbeans.api.project.Project
+import org.netbeans.api.project.ui.OpenProjects
+import org.openide.filesystems.FileObject
+
+object KotlinPsiManager {
+
+ private val cachedKtFiles = hashMapOf<FileObject, KtFile>()
+
+ fun getFilesByProject(project: Project,
+ test: Boolean = true) = project.getKotlinSources()
+ ?.getSourceGroups(KotlinProjectConstants.KOTLIN_SOURCE, test)
+ ?.flatMap { it.rootFolder.children.toList() }
+ ?.filter { it.isKotlinFile() }
+ ?.toSet() ?: emptySet()
+
+ private fun parseFile(file: FileObject): KtFile? =
+ parseText(StringUtilRt.convertLineSeparators(file.asText()), file)
+
+ fun parseText(text: String, file: FileObject): KtFile? {
+ StringUtil.assertValidSeparators(text)
+ val kotlinProject = ProjectUtils.getKotlinProjectForFileObject(file) ?: ProjectUtils.getValidProject()
+ if (kotlinProject == null) {
+ KotlinLogger.INSTANCE.logWarning("Project is null")
+ return null
+ }
+
+ val project = KotlinEnvironment.getEnvironment(kotlinProject).project
+ val virtualFile = KotlinLightVirtualFile(file, text)
+ virtualFile.charset = CharsetToolkit.UTF8_CHARSET
+ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
+
+ return psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile
+ }
+
+ fun parseTextForDiagnostic(text: String, file: FileObject): KtFile? {
+ StringUtil.assertValidSeparators(text)
+ if (cachedKtFiles.containsKey(file)) {
+ updatePsiFile(text, file)
+ } else {
+ try {
+ val ktFile = parseFile(file) ?: return null
+ cachedKtFiles.put(file, ktFile)
+ } catch (ex: IOException) {
+ KotlinLogger.INSTANCE.logException("parseFile exception", ex)
+ }
+ }
+
+ return cachedKtFiles[file]
+ }
+
+ fun getParsedFile(file: FileObject): KtFile? {
+ if (!cachedKtFiles.containsKey(file)) {
+ val ktFile = parseFile(file) ?: return null
+ cachedKtFiles.put(file, ktFile)
+ } else {
+ updatePsiFile(file)
+ }
+ return cachedKtFiles[file]
+ }
+
+ private fun updatePsiFile(file: FileObject) {
+ try {
+ val code = file.asText()
+ val sourceCodeWithoutCR = StringUtilRt.convertLineSeparators(code)
+ val currentParsedFile = cachedKtFiles[file] ?: return
+ if (currentParsedFile.text != sourceCodeWithoutCR) {
+ val ktFile = parseText(sourceCodeWithoutCR, file) ?: return
+ cachedKtFiles.put(file, ktFile)
+ }
+ } catch (ex: IOException) {
+ KotlinLogger.INSTANCE.logWarning("Couldn't update psi file")
+ }
+ }
+
+ private fun updatePsiFile(sourceCode: String, file: FileObject) {
+ try {
+ val sourceCodeWithoutCR = StringUtilRt.convertLineSeparators(sourceCode)
+ val currentParsedFile = cachedKtFiles[file] ?: return
+ if (currentParsedFile.text != sourceCodeWithoutCR) {
+ val ktFile = parseText(sourceCodeWithoutCR, file) ?: return
+ cachedKtFiles.put(file, ktFile)
+ }
+ } catch (ex: IOException) {
+ KotlinLogger.INSTANCE.logWarning("Couldn't update psi file")
+ }
+ }
+
+ fun getParsedKtFileForSyntaxHighlighting(text: String): KtFile? {
+ val sourceCode = StringUtilRt.convertLineSeparators(text)
+ var kotlinProject = OpenProjects.getDefault().openProjects.firstOrNull { it.checkProject() }
+
+ if (kotlinProject == null) kotlinProject = KotlinMockProject.getMockProject() ?: return null
+
+ val project = KotlinEnvironment.getEnvironment(kotlinProject).project
+ val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
+
+ return psiFileFactory.createFileFromText(KotlinLanguage.INSTANCE, sourceCode) as KtFile
+ }
+}
+
+
+fun FileObject.isKotlinFile() = KotlinFileType.INSTANCE.defaultExtension == ext
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/bundledcompiler/BundledCompiler.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/bundledcompiler/BundledCompiler.java
new file mode 100644
index 0000000..00ca688
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/bundledcompiler/BundledCompiler.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.bundledcompiler;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.openide.filesystems.FileLock;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.modules.Places;
+
+public class BundledCompiler {
+
+ public static final String KOTLIN_VERSION = "1.1.1";
+
+ private static void unZipFile(InputStream fis, FileObject destDir) throws IOException {
+ try {
+ ZipInputStream str = new ZipInputStream(fis);
+ ZipEntry entry;
+ while ((entry = str.getNextEntry()) != null) {
+ if (entry.isDirectory()) {
+ FileUtil.createFolder(destDir, entry.getName());
+ } else {
+ FileObject fo = FileUtil.createData(destDir, entry.getName());
+ FileLock lock = fo.lock();
+ try {
+ OutputStream out = fo.getOutputStream(lock);
+ try {
+ FileUtil.copy(str, out);
+ } finally {
+ out.close();
+ }
+ } finally {
+ lock.releaseLock();
+ }
+ }
+ }
+ } finally {
+ fis.close();
+ }
+ }
+
+ public static void getKotlinc() {
+ try {
+ InputStream inputStream = BundledCompiler.class.getClassLoader().getResourceAsStream("org/jetbrains/kotlin/kotlinc/kotlinc.zip");
+
+ File userDirectory = Places.getUserDirectory();
+ if (userDirectory == null) {
+ KotlinLogger.INSTANCE.logWarning("User directory is null");
+ return;
+ }
+ FileObject destFileObj = FileUtil.toFileObject(userDirectory);
+ unZipFile(inputStream, destFileObj);
+ } catch (IOException ex) {
+ KotlinLogger.INSTANCE.logException("unZipFile() exception", ex);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KeywordCompletionProposal.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KeywordCompletionProposal.kt
new file mode 100644
index 0000000..bf1c51a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KeywordCompletionProposal.kt
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import org.netbeans.modules.csl.spi.DefaultCompletionProposal
+import org.netbeans.modules.csl.api.ElementKind
+import org.netbeans.modules.csl.api.HtmlFormatter
+import javax.swing.text.Document
+
+class KeywordCompletionProposal(private val keyword: String,
+ private val idenStartOffset: Int,
+ val prefix: String) : DefaultCompletionProposal(), InsertableProposal {
+ override fun getElement() = null
+
+ override fun getSortPrioOverride() = 5
+ override fun getKind() = ElementKind.KEYWORD
+ override fun getLhsHtml(formatter: HtmlFormatter) = keyword
+ override fun getRhsHtml(formatter: HtmlFormatter) = null
+ override fun getInsertPrefix() = keyword
+ override fun getName() = keyword
+ override fun getSortText() = keyword
+ override fun getAnchorOffset() = idenStartOffset
+ override fun doInsert(document: Document) {
+ document.remove(idenStartOffset, prefix.length)
+ document.insertString(idenStartOffset, keyword, null)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCodeCompletionHandler.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCodeCompletionHandler.kt
new file mode 100644
index 0000000..d4f3f27
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCodeCompletionHandler.kt
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import java.util.concurrent.Callable
+import javax.swing.text.Document
+import javax.swing.text.JTextComponent
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.modules.csl.api.CodeCompletionContext
+import org.netbeans.modules.csl.api.CodeCompletionHandler2
+import org.netbeans.modules.csl.api.CodeCompletionResult
+import org.netbeans.modules.csl.api.CompletionProposal
+import org.netbeans.modules.csl.api.Documentation
+import org.netbeans.modules.csl.api.ElementHandle
+import org.netbeans.modules.csl.api.ParameterInfo
+import org.netbeans.modules.csl.spi.ParserResult
+import org.netbeans.modules.csl.api.CodeCompletionHandler.QueryType
+
+class KotlinCodeCompletionHandler : CodeCompletionHandler2 {
+
+ override fun documentElement(info: ParserResult, element: ElementHandle,
+ cancel: Callable<Boolean>): Documentation {
+ return if (element is ElementHandle.UrlHandle)
+ return Documentation.create(element.url)
+ else Documentation.create("")
+ }
+
+ override fun document(info: ParserResult, element: ElementHandle) = ""
+
+ override fun resolveLink(link: String, handle: ElementHandle) = null
+
+ override fun getPrefix(info: ParserResult, caretOffset: Int, upToOffset: Boolean) = null
+
+ override fun resolveTemplateVariable(variable: String, info: ParserResult, caretOffset: Int,
+ name: String, parameters: Map<*, *>) = null
+
+ override fun getApplicableTemplates(doc: Document, selectionBegin: Int, selectionEnd: Int) = emptySet<String>()
+
+ override fun parameters(info: ParserResult, caretOffset: Int, proposal: CompletionProposal): ParameterInfo = ParameterInfo.NONE
+
+ override fun getAutoQuery(component: JTextComponent, typedText: String): QueryType {
+ if (typedText.isNotEmpty()) {
+ if (typedText.endsWith(".")) return QueryType.COMPLETION
+ }
+ return QueryType.NONE
+ }
+
+ override fun complete(context: CodeCompletionContext): CodeCompletionResult? {
+ val parserResult = context.parserResult as KotlinParserResult
+ val file = parserResult.snapshot.source.fileObject
+
+ val doc = ProjectUtils.getDocumentFromFileObject(file)
+ val caretOffset = context.caretOffset
+ val analysisResultWithProvider = parserResult.analysisResult ?: return null
+ val prefix = context.prefix ?: ""
+
+ return KotlinCodeCompletionResult(doc, caretOffset, analysisResultWithProvider, prefix)
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCodeCompletionResult.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCodeCompletionResult.kt
new file mode 100644
index 0000000..0ff32e5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCodeCompletionResult.kt
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import javax.swing.text.Document
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.netbeans.modules.csl.api.CodeCompletionResult
+import org.netbeans.modules.csl.api.CompletionProposal
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+class KotlinCodeCompletionResult(private val doc: Document, offset: Int,
+ analysisResult: AnalysisResultWithProvider,
+ prefix: String) : CodeCompletionResult() {
+
+ private val proposals: List<CompletionProposal> = createProposals(doc, offset, analysisResult, prefix)
+
+ override fun getItems() = proposals
+ override fun isTruncated() = false
+ override fun isFilterable() = false
+
+ override fun insert(item: CompletionProposal): Boolean {
+ (item as InsertableProposal).doInsert(doc)
+ return true
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCompletionProposal.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCompletionProposal.kt
new file mode 100644
index 0000000..0503d19
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinCompletionProposal.kt
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import com.intellij.psi.util.PsiTreeUtil
+import javax.swing.ImageIcon
+import javax.swing.SwingUtilities
+import javax.swing.text.StyledDocument
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
+import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
+import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
+import org.jetbrains.kotlin.descriptors.VariableDescriptor
+import org.jetbrains.kotlin.psi.KtImportDirective
+import org.jetbrains.kotlin.renderer.DescriptorRenderer
+import org.jetbrains.kotlin.utils.KotlinImageProvider
+import org.netbeans.modules.csl.api.ElementHandle
+import org.netbeans.modules.csl.api.HtmlFormatter
+import org.netbeans.modules.csl.spi.DefaultCompletionProposal
+import org.jetbrains.kotlin.navigation.netbeans.getElementWithSource
+import org.jetbrains.kotlin.resolve.lang.java.resolver.NetBeansJavaSourceElement
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.navigation.netbeans.moveCaretToOffset
+import org.jetbrains.kotlin.resolve.lang.java.getJavaDoc
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import javax.swing.text.Document
+import org.netbeans.modules.csl.api.ElementKind
+
+class KotlinCompletionProposal(private val idenStartOffset: Int,
+ val descriptor: DeclarationDescriptor, val doc: StyledDocument,
+ val prefix: String, val project: Project) : DefaultCompletionProposal(), InsertableProposal {
+
+ val text: String = descriptor.name.identifier
+ private val proposal: String = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(descriptor)
+ val type: String
+ private val proposalName: String
+ private val FIELD_ICON: ImageIcon? = KotlinImageProvider.getImage(descriptor)
+
+ init {
+ val splitted = proposal.split(":")
+ proposalName = splitted[0]
+ type = if (splitted.size > 1) splitted[1] else ""
+ }
+
+ override fun getElement(): ElementHandle? {
+ val source = getElementWithSource(descriptor, project) as? NetBeansJavaSourceElement ?: return null
+ val handle = source.getElementBinding()
+ val doc = handle.getJavaDoc(project) ?: return null
+
+ return ElementHandle.UrlHandle(doc.rawCommentText)
+ }
+
+ override fun getLhsHtml(formatter: HtmlFormatter) = proposalName
+ override fun getRhsHtml(formatter: HtmlFormatter) = type
+ override fun getName() = proposalName
+ override fun getInsertPrefix() = proposalName
+ override fun getSortText() = proposalName
+ override fun getAnchorOffset() = idenStartOffset
+ override fun getIcon() = FIELD_ICON
+
+ override fun getKind() = when (descriptor) {
+ is VariableDescriptor -> ElementKind.FIELD
+ is FunctionDescriptor -> ElementKind.METHOD
+ is ClassDescriptor -> ElementKind.CLASS
+ is PackageFragmentDescriptor, is PackageViewDescriptor -> ElementKind.PACKAGE
+ else -> ElementKind.OTHER
+ }
+
+ override fun getSortPrioOverride() = when (descriptor) {
+ is VariableDescriptor -> 20
+ is FunctionDescriptor -> 30
+ is ClassDescriptor -> 40
+ is PackageFragmentDescriptor, is PackageViewDescriptor -> 10
+ else -> 150
+ }
+
+ private fun functionAction() {
+ val functionDescriptor = descriptor as FunctionDescriptor
+ val params = functionDescriptor.valueParameters
+
+ val importDirective: KtImportDirective? = PsiTreeUtil.getNonStrictParentOfType(KotlinParser.file?.findElementAt(idenStartOffset - 1),
+ KtImportDirective::class.java)
+ val isImport = importDirective != null
+
+ doc.remove(idenStartOffset, prefix.length)
+
+ if (isImport) {
+ doc.insertString(idenStartOffset, text, null)
+ SwingUtilities.invokeLater { moveCaretToOffset(doc, idenStartOffset + text.length) }
+
+ return
+ }
+
+ if (params.size == 1 && name.contains("->")) {
+ doc.insertString(idenStartOffset, "$text { }", null)
+ SwingUtilities.invokeLater { moveCaretToOffset(doc, idenStartOffset + "$text { ".length) }
+
+ return
+ }
+
+ doc.insertString(idenStartOffset, "$text${params.joinToString(prefix = "(", postfix = ")") { getValueParameter(it) }}", null)
+ if (params.isNotEmpty()) {
+ SwingUtilities.invokeLater { moveCaretToOffset(doc, idenStartOffset + text.length + 1) }
+ }
+ }
+
+ private fun getValueParameter(desc: ValueParameterDescriptor): String {
+ val kotlinType = desc.type
+ val classifierDescriptor = kotlinType.constructor.declarationDescriptor ?: return desc.name.asString()
+
+ val typeName = classifierDescriptor.name.asString()
+ return getValueForType(typeName) ?: desc.name.asString()
+ }
+
+ override fun doInsert(document: Document) {
+ if (descriptor is FunctionDescriptor) {
+ functionAction()
+ } else {
+ document.remove(idenStartOffset, prefix.length)
+ document.insertString(idenStartOffset, text, null)
+ }
+ }
+
+}
+
+interface InsertableProposal {
+ fun doInsert(document: Document)
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinKeywordCompletion.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinKeywordCompletion.kt
new file mode 100644
index 0000000..e63ca8d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/KotlinKeywordCompletion.kt
@@ -0,0 +1,420 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiComment
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiErrorElement
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.filters.ClassFilter
+import com.intellij.psi.filters.ElementFilter
+import com.intellij.psi.filters.NotFilter
+import com.intellij.psi.filters.OrFilter
+import com.intellij.psi.filters.position.PositionElementFilter
+import com.intellij.psi.tree.IElementType
+import com.intellij.psi.tree.TokenSet
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.renderer.render
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.ANNOTATION_CLASS
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.CLASS_ONLY
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.ENUM_CLASS
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.ENUM_ENTRY
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.FUNCTION
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.INNER_CLASS
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.INTERFACE
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.MEMBER_FUNCTION
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.MEMBER_PROPERTY
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.OBJECT
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.PROPERTY
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.TOP_LEVEL_FUNCTION
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.TOP_LEVEL_PROPERTY
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.TYPE_PARAMETER
+import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.VALUE_PARAMETER
+import org.jetbrains.kotlin.lexer.KtKeywordToken
+import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
+import org.jetbrains.kotlin.lexer.KtTokens.*
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.*
+import org.jetbrains.kotlin.resolve.ModifierCheckerCore
+import java.util.ArrayList
+import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
+import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.netbeans.modules.csl.api.CompletionProposal
+
+// This code is mostly copied from Idea plugin
+object KeywordCompletion {
+ private val ALL_KEYWORDS = (KEYWORDS.types + SOFT_KEYWORDS.types).map { it as KtKeywordToken }
+
+ private val KEYWORDS_TO_IGNORE_PREFIX = TokenSet.create(OVERRIDE_KEYWORD /* it's needed to complete overrides that should be work by member name too */)
+
+ private val COMPOUND_KEYWORDS = mapOf<KtKeywordToken, KtKeywordToken>(
+ COMPANION_KEYWORD to OBJECT_KEYWORD,
+ ENUM_KEYWORD to CLASS_KEYWORD,
+ ANNOTATION_KEYWORD to CLASS_KEYWORD
+ )
+
+ fun complete(position: PsiElement, prefix: String, isJvmModule: Boolean, consumer: (String) -> Unit) {
+ if (!GENERAL_FILTER.isAcceptable(position, position)) return
+
+ val parserFilter = buildFilter(position)
+ for (keywordToken in ALL_KEYWORDS) {
+ var keyword = keywordToken.value
+
+ val nextKeyword = COMPOUND_KEYWORDS[keywordToken]
+ if (nextKeyword != null) {
+ fun PsiElement.isSpace() = this is PsiWhiteSpace && '\n' !in getText()
+
+ var next = position.nextLeaf { !(it.isSpace() || it.text == "$") }?.text
+ if (next != null && next.startsWith("$")) {
+ next = next.substring(1)
+ }
+ if (next != nextKeyword.value) {
+ keyword += " ${nextKeyword.value}"
+ }
+ }
+
+ if (keywordToken == DYNAMIC_KEYWORD && isJvmModule) continue // not supported for JVM
+
+ // we use simple matching by prefix, not prefix matcher from completion
+ if (!keyword.startsWith(prefix) && keywordToken !in KEYWORDS_TO_IGNORE_PREFIX) continue
+
+ if (!parserFilter(keywordToken)) continue
+
+ consumer(keyword)
+ }
+ }
+
+ private val GENERAL_FILTER = NotFilter(OrFilter(
+ CommentFilter(),
+ ParentFilter(ClassFilter(KtLiteralStringTemplateEntry::class.java)),
+ ParentFilter(ClassFilter(KtConstantExpression::class.java)),
+ LeftNeighbour(TextFilter(".")),
+ LeftNeighbour(TextFilter("?."))
+ ))
+
+ private class CommentFilter : ElementFilter {
+ override fun isAcceptable(element: Any?, context: PsiElement?)
+ = (element is PsiElement) && KtPsiUtil.isInComment(element)
+
+ override fun isClassAcceptable(hintClass: Class<out Any?>)
+ = true
+ }
+
+ private class ParentFilter(filter: ElementFilter) : PositionElementFilter() {
+ init {
+ setFilter(filter)
+ }
+
+ override fun isAcceptable(element: Any?, context: PsiElement?): Boolean {
+ val parent = (element as? PsiElement)?.parent
+ return parent != null && (filter?.isAcceptable(parent, context) ?: true)
+ }
+ }
+
+ private fun buildFilter(position: PsiElement): (KtKeywordToken) -> Boolean {
+ var parent = position.parent
+ var prevParent = position
+ while (parent != null) {
+ when (parent) {
+ is KtBlockExpression -> {
+ var prefixText = "fun foo() { "
+ if (prevParent is KtExpression) {
+ // check that we are right after a try-expression without finally-block
+ val prevLeaf = prevParent.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment && it !is PsiErrorElement }
+ if (prevLeaf?.node?.elementType == KtTokens.RBRACE) {
+ val blockParent = (prevLeaf?.parent as? KtBlockExpression)?.parent
+ when (blockParent) {
+ is KtTryExpression -> prefixText += "try {}\n"
+ is KtCatchClause -> prefixText += "try {} catch (e: E) {}\n"
+ }
+ }
+
+ return buildFilterWithContext(prefixText, prevParent, position)
+ } else {
+ val lastExpression = prevParent
+ .siblings(forward = false, withItself = false)
+ .firstIsInstanceOrNull<KtExpression>()
+ if (lastExpression != null) {
+ val contextAfterExpression = lastExpression
+ .siblings(forward = true, withItself = false)
+ .takeWhile { it != prevParent }
+ .joinToString { it.text }
+ return buildFilterWithContext("${prefixText}x$contextAfterExpression", prevParent, position)
+ }
+ }
+ }
+
+ is KtDeclarationWithInitializer -> {
+ val initializer = parent.initializer
+ if (initializer != null && prevParent == initializer) {
+ return buildFilterWithContext("val v = ", initializer, position)
+ }
+ }
+
+ is KtParameter -> {
+ val default = parent.defaultValue
+ if (default != null && prevParent == default) {
+ return buildFilterWithContext("val v = ", default, position)
+ }
+ }
+ }
+
+ if (parent is KtDeclaration) {
+ val scope = parent.parent
+ when (scope) {
+ is KtClassOrObject -> {
+ return if (parent is KtPrimaryConstructor) {
+ buildFilterWithReducedContext("class X ", parent, position)
+ } else {
+ buildFilterWithReducedContext("class X { ", parent, position)
+ }
+ }
+
+ is KtFile -> return buildFilterWithReducedContext("", parent, position)
+ }
+ }
+
+ prevParent = parent
+ parent = parent.parent
+ }
+
+ return buildFilterWithReducedContext("", null, position)
+ }
+
+ private fun buildFilterWithContext(prefixText: String,
+ contextElement: PsiElement,
+ position: PsiElement): (KtKeywordToken) -> Boolean {
+ val offset = position.getStartOffsetInAncestor(contextElement)
+ val truncatedContext = contextElement.text!!.substring(0, offset)
+ return buildFilterByText("$prefixText$truncatedContext", contextElement.project)
+ }
+
+ private fun buildFilterWithReducedContext(prefixText: String,
+ contextElement: PsiElement?,
+ position: PsiElement): (KtKeywordToken) -> Boolean {
+ val builder = StringBuilder()
+ buildReducedContextBefore(builder, position, contextElement)
+ return buildFilterByText("$prefixText$builder", position.project)
+ }
+
+
+ private fun buildFilterByText(prefixText: String, project: Project): (KtKeywordToken) -> Boolean {
+ val psiFactory = KtPsiFactory(project)
+ return fun(keywordTokenType): Boolean {
+ val postfix = if (prefixText.endsWith("@")) ":X" else " X"
+ val file = psiFactory.createFile("$prefixText${keywordTokenType.value}$postfix")
+ val elementAt = file.findElementAt(prefixText.length)!!
+
+ when {
+ !elementAt.node!!.elementType.matchesKeyword(keywordTokenType) -> return false
+
+ elementAt.getNonStrictParentOfType<PsiErrorElement>() != null -> return false
+
+ isErrorElementBefore(elementAt) -> return false
+
+ keywordTokenType !is KtModifierKeywordToken -> return true
+
+ else -> {
+ if (elementAt.parent !is KtModifierList) return true
+ val container = elementAt.parent.parent
+ val possibleTargets = when (container) {
+ is KtParameter -> {
+ if (container.ownerFunction is KtPrimaryConstructor)
+ listOf(VALUE_PARAMETER, MEMBER_PROPERTY)
+ else
+ listOf(VALUE_PARAMETER)
+ }
+
+ is KtTypeParameter -> listOf(TYPE_PARAMETER)
+
+ is KtEnumEntry -> listOf(ENUM_ENTRY)
+
+ is KtClassBody -> listOf(CLASS_ONLY, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS, INNER_CLASS, MEMBER_FUNCTION, MEMBER_PROPERTY, FUNCTION, PROPERTY)
+
+ is KtFile -> listOf(CLASS_ONLY, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS, TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, FUNCTION, PROPERTY)
+
+ else -> null
+ }
+ val modifierTargets = ModifierCheckerCore.possibleTargetMap[keywordTokenType]
+ if (modifierTargets != null && possibleTargets != null && possibleTargets.none { it in modifierTargets }) return false
+
+ val ownerDeclaration = container?.getParentOfType<KtDeclaration>(strict = true)
+ val parentTarget = when (ownerDeclaration) {
+ null -> KotlinTarget.FILE
+
+ is KtClass -> {
+ when {
+ ownerDeclaration.isInterface() -> KotlinTarget.INTERFACE
+ ownerDeclaration.isEnum() -> KotlinTarget.ENUM_CLASS
+ ownerDeclaration.isAnnotation() -> KotlinTarget.ANNOTATION_CLASS
+ ownerDeclaration.isInner() -> KotlinTarget.INNER_CLASS
+ else -> KotlinTarget.CLASS_ONLY
+ }
+ }
+
+ is KtObjectDeclaration -> if (ownerDeclaration.isObjectLiteral()) KotlinTarget.OBJECT_LITERAL else KotlinTarget.OBJECT
+
+ else -> return true
+ }
+
+ val modifierParents = ModifierCheckerCore.possibleParentTargetMap[keywordTokenType]
+ if (modifierParents != null && parentTarget !in modifierParents) return false
+
+ val deprecatedParents = ModifierCheckerCore.deprecatedParentTargetMap[keywordTokenType]
+ if (deprecatedParents != null && parentTarget in deprecatedParents) return false
+
+ return true
+ }
+ }
+ }
+ }
+
+ private fun isErrorElementBefore(token: PsiElement): Boolean {
+ for (leaf in token.prevLeafs) {
+ if (leaf is PsiWhiteSpace || leaf is PsiComment) continue
+ if (leaf.parentsWithSelf.any { it is PsiErrorElement }) return true
+ if (leaf.textLength != 0) break
+ }
+ return false
+ }
+
+ private fun IElementType.matchesKeyword(keywordType: KtKeywordToken): Boolean =
+ when (this) {
+ keywordType -> true
+ NOT_IN -> keywordType == IN_KEYWORD
+ NOT_IS -> keywordType == IS_KEYWORD
+ else -> false
+ }
+
+
+ // builds text within scope (or from the start of the file) before position element excluding almost all declarations
+ private fun buildReducedContextBefore(builder: StringBuilder, position: PsiElement, scope: PsiElement?) {
+ if (position == scope) return
+ val parent = position.parent ?: return
+
+ buildReducedContextBefore(builder, parent, scope)
+
+ val prevDeclaration = position.siblings(forward = false, withItself = false).firstOrNull { it is KtDeclaration }
+
+ var child = parent.firstChild
+ while (child != position) {
+ if (child is KtDeclaration) {
+ if (child == prevDeclaration) {
+ builder.appendReducedText(child)
+ }
+ } else {
+ builder.append(child!!.text)
+ }
+
+ child = child.nextSibling
+ }
+ }
+
+ private fun StringBuilder.appendReducedText(element: PsiElement) {
+ var child = element.firstChild
+ if (child == null) {
+ append(element.text!!)
+ } else {
+ while (child != null) {
+ when (child) {
+ is KtBlockExpression, is KtClassBody -> append("{}")
+ else -> appendReducedText(child)
+ }
+
+ child = child.nextSibling
+ }
+ }
+ }
+
+ private fun PsiElement.getStartOffsetInAncestor(ancestor: PsiElement): Int {
+ if (ancestor == this) return 0
+ return parent!!.getStartOffsetInAncestor(ancestor) + startOffsetInParent
+ }
+}
+
+fun breakOrContinueExpressionItems(position: KtElement, breakOrContinue: String): Collection<String> {
+ val result = ArrayList<String>()
+
+ parentsLoop@
+ for (parent in position.parentsWithSelf) {
+ when (parent) {
+ is KtLoopExpression -> {
+ if (result.isEmpty()) {
+ result.add(breakOrContinue)
+ }
+
+ val label = (parent.parent as? KtLabeledExpression)?.getLabelNameAsName()
+ if (label != null) {
+ result.add("$breakOrContinue${label.labelNameToTail()}")
+ }
+ }
+
+ is KtDeclarationWithBody -> break@parentsLoop //TODO: support non-local break's&continue's when they are supported by compiler
+ }
+ }
+ return result
+}
+
+private fun Name?.labelNameToTail(): String = if (this != null) "@${render()}" else ""
+
+inline fun <reified T : Any> Sequence<*>.firstIsInstanceOrNull(): T? {
+ for (element in this) if (element is T) return element
+ return null
+}
+
+inline fun <reified T : PsiElement> PsiElement.getNonStrictParentOfType(): T? =
+ PsiTreeUtil.getParentOfType(this, T::class.java, false)
+
+inline fun <reified T : PsiElement> PsiElement.getParentOfType(strict: Boolean): T? =
+ PsiTreeUtil.getParentOfType(this, T::class.java, strict)
+
+fun generateKeywordProposals(identifierPart: String,
+ expression: PsiElement, offset: Int, prefix: String): List<CompletionProposal> {
+ val callTypeAndReceiver = if (expression is KtSimpleNameExpression) CallTypeAndReceiver.detect(expression) else null
+
+ return arrayListOf<String>().apply {
+ KeywordCompletion.complete(expression, identifierPart, true) { keywordProposal ->
+ if (!applicableNameFor(identifierPart, keywordProposal)) return@complete
+
+ when (keywordProposal) {
+ "break", "continue" -> {
+ if (expression is KtSimpleNameExpression) {
+ addAll(breakOrContinueExpressionItems(expression, keywordProposal))
+ }
+ }
+
+ "class" -> {
+ if (callTypeAndReceiver !is CallTypeAndReceiver.CALLABLE_REFERENCE) {
+ add(keywordProposal)
+ }
+ }
+
+ "this", "return" -> {
+ if (expression is KtExpression) {
+ add(keywordProposal)
+ }
+ }
+
+ else -> add(keywordProposal)
+ }
+ }
+ }.map { KeywordCompletionProposal(it, offset, prefix) }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/completionUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/completionUtils.kt
new file mode 100644
index 0000000..129d486
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/completionUtils.kt
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import com.intellij.openapi.util.text.StringUtilRt
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import javax.swing.text.Document
+import javax.swing.text.StyledDocument
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.resolve.KotlinResolutionFacade
+import org.jetbrains.kotlin.utils.LineEndUtil
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.descriptors.Visibilities
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.KtClassBody
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.scopes.LexicalScope
+import org.openide.filesystems.FileObject
+import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
+import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
+import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
+import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
+import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
+import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
+import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
+import org.netbeans.modules.csl.api.CompletionProposal
+
+fun applicableNameFor(prefix: String, name: Name): Boolean {
+ if (!name.isSpecial) {
+ val identifier = name.identifier
+
+ return identifier.toLowerCase().startsWith(prefix.toLowerCase())
+ }
+ return false
+}
+
+fun applicableNameFor(prefix: String, completion: String) = completion.startsWith(prefix) || completion.toLowerCase().startsWith(prefix)
+
+fun getResolutionScope(psiElement: PsiElement, bindingContext: BindingContext): LexicalScope? {
+ psiElement.parentsWithSelf.forEach {
+ if (it is KtElement) {
+ val scope = bindingContext.get(BindingContext.LEXICAL_SCOPE, it)
+ if (scope != null) return scope
+ }
+ if (it is KtClassBody) {
+ val classDescriptor = bindingContext.get(BindingContext.CLASS, it.parent) as? ClassDescriptorWithResolutionScopes
+ if (classDescriptor != null) return classDescriptor.scopeForMemberDeclarationResolution
+ }
+ }
+
+ return null
+}
+
+private fun TypeParameterDescriptor.isVisible(descriptor: DeclarationDescriptor): Boolean {
+ val owner = this.containingDeclaration
+ var parent: DeclarationDescriptor? = descriptor
+
+ while (parent != null) {
+ if (parent == owner) return true
+ if (parent is ClassDescriptor && !parent.isInner) return false
+
+ parent = parent.containingDeclaration
+ }
+
+ return true
+}
+
+private fun DeclarationDescriptorWithVisibility.isVisible(from: DeclarationDescriptor,
+ bindingContext: BindingContext?,
+ element: KtSimpleNameExpression?): Boolean {
+ if (Visibilities.isVisibleWithAnyReceiver(this, from)) return true
+ if (bindingContext == null || element == null) return false
+
+ val receiverExpression = element.getReceiverExpression()
+ if (receiverExpression != null) {
+ val receiverType = bindingContext.getType(receiverExpression) ?: return false
+ val explicitReceiver = ExpressionReceiver.create(receiverExpression, receiverType, bindingContext)
+
+ return Visibilities.isVisible(explicitReceiver, this, from)
+ } else {
+ val resolutionScope = getResolutionScope(element, bindingContext) ?: return false
+ resolutionScope.getImplicitReceiversHierarchy().forEach {
+ if (Visibilities.isVisible(it.value, this, from)) return true
+ }
+
+ return false
+ }
+}
+
+fun getReferenceVariants(simpleNameExpression: KtSimpleNameExpression,
+ nameFilter: (Name) -> Boolean,
+ file: FileObject,
+ result: AnalysisResultWithProvider? = null): Collection<DeclarationDescriptor> {
+ val project = ProjectUtils.getKotlinProjectForFileObject(file) ?: return emptyList()
+ val resultWithProvider = result ?: KotlinAnalyzer.analyzeFile(project, simpleNameExpression.containingKtFile)
+ val analysisResult = resultWithProvider.analysisResult
+ val container = resultWithProvider.componentProvider
+
+ val inDescriptor = getResolutionScope(simpleNameExpression.getReferencedNameElement(),
+ analysisResult.bindingContext)?.ownerDescriptor ?: return emptyList()
+
+ val visibilityFilter: (DeclarationDescriptor) -> Boolean = {
+ when (it) {
+ is TypeParameterDescriptor -> it.isVisible(inDescriptor)
+ is DeclarationDescriptorWithVisibility -> it.isVisible(inDescriptor, analysisResult.bindingContext, simpleNameExpression)
+ else -> true
+ }
+ }
+
+ val helper = ReferenceVariantsHelper(analysisResult.bindingContext,
+ KotlinResolutionFacade(project, container, analysisResult.moduleDescriptor),
+ analysisResult.moduleDescriptor, visibilityFilter)
+ return helper.getReferenceVariants(simpleNameExpression, DescriptorKindFilter.ALL, nameFilter, false, false, false, null)
+}
+
+fun getSimpleNameExpression(identOffset: Int): KtSimpleNameExpression? {
+ val psi = KotlinParser.file?.findElementAt(identOffset) ?: return null
+ return PsiTreeUtil.getParentOfType(psi, KtSimpleNameExpression::class.java)
+}
+
+fun getSimpleNameExpression(file: FileObject, identOffset: Int, editorText: String): KtSimpleNameExpression? {
+ val sourceCodeWithMarker = StringBuilder(editorText).insert(identOffset, "KotlinNetBeans").toString()
+ val ktFile = KotlinPsiManager.parseText(StringUtilRt.convertLineSeparators(sourceCodeWithMarker),
+ file) ?: return null
+ val offsetWithoutCR = LineEndUtil.convertCrToDocumentOffset(sourceCodeWithMarker, identOffset)
+ val psiElement = ktFile.findElementAt(offsetWithoutCR)
+
+ return PsiTreeUtil.getParentOfType(psiElement, KtSimpleNameExpression::class.java)
+}
+
+fun getIdentifierStartOffset(text: String, offset: Int): Int {
+ var identStartOffset = offset
+ while ((identStartOffset != 0) && Character.isUnicodeIdentifierPart(text[identStartOffset - 1])){
+ identStartOffset--
+ }
+
+ return identStartOffset
+}
+
+private fun generateBasicCompletionProposals(file: FileObject, identifierPart: String,
+ identOffset: Int, editorText: String,
+ result: AnalysisResultWithProvider): Collection<DeclarationDescriptor> {
+ var simpleNameExpression = getSimpleNameExpression(identOffset)
+ if (simpleNameExpression != null) return getReferenceVariants(simpleNameExpression,
+ {applicableNameFor(identifierPart, it)}, file, result)
+
+ simpleNameExpression = getSimpleNameExpression(file, identOffset, editorText) ?: return emptyList()
+ return getReferenceVariants(simpleNameExpression, {applicableNameFor(identifierPart, it)}, file)
+}
+
+
+fun createProposals(doc: Document, caretOffset: Int,
+ result: AnalysisResultWithProvider,
+ prefix: String): List<CompletionProposal> {
+ val file = ProjectUtils.getFileObjectForDocument(doc) ?: return emptyList()
+ val styledDoc = doc as? StyledDocument ?: return emptyList()
+ val editorText = styledDoc.getText(0, styledDoc.length)
+
+ val identOffset = getIdentifierStartOffset(editorText, caretOffset)
+ val identifierPart = editorText.substring(identOffset, caretOffset)
+ val project = ProjectUtils.getKotlinProjectForFileObject(file) ?: return emptyList()
+ val descriptors = generateBasicCompletionProposals(file, identifierPart, identOffset, editorText, result)
+
+ val proposals: MutableList<CompletionProposal> = descriptors.filter { it !is JavaClassConstructorDescriptor }
+ .map { KotlinCompletionProposal(identOffset, it, styledDoc, prefix, project) }
+ .toMutableList()
+ val ktFile = KotlinParser.file ?: ProjectUtils.getKtFile(editorText, file) ?: return proposals
+ val psiElement = ktFile.findElementAt(identOffset) ?: return proposals
+
+ proposals.addAll(generateKeywordProposals(identifierPart, psiElement, identOffset, prefix))
+ val simpleNameExpression = PsiTreeUtil.getParentOfType(psiElement, KtSimpleNameExpression::class.java)
+ if (simpleNameExpression != null) {
+ proposals.addAll(generateNonImportedCompletionProposals(prefix, ktFile, simpleNameExpression, project, identOffset))
+ }
+
+ return proposals.distinctBy { it.sortText }
+}
+
+fun getValueForType(type: String) = when(type) {
+ "Int" -> "0"
+ "Long" -> "0"
+ "Short" -> "0"
+ "Double" -> "0.0"
+ "Float" -> "0.0"
+ "String" -> "\"\""
+ "Char" -> "\"\""
+ "Boolean" -> "true"
+ else -> null
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/filterPositionUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/filterPositionUtils.kt
new file mode 100644
index 0000000..8c102f7
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/filterPositionUtils.kt
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import com.intellij.psi.PsiComment
+import com.intellij.psi.PsiElement
+import com.intellij.psi.TokenType
+import com.intellij.psi.impl.source.tree.TreeUtil
+
+fun PsiElement.searchNonSpaceNonCommentBack(strict: Boolean): PsiElement? {
+ if (node == null) return null
+
+ var leftNeighbour = TreeUtil.prevLeaf(node)
+ if (!strict) {
+ while (leftNeighbour != null && (leftNeighbour.elementType == TokenType.WHITE_SPACE
+ || leftNeighbour.psi is PsiComment)) {
+ leftNeighbour = TreeUtil.prevLeaf(leftNeighbour)
+ }
+ }
+
+ return if (leftNeighbour != null) leftNeighbour.psi else null
+}
+
+fun PsiElement.searchNonSpaceNonCommentBack() = searchNonSpaceNonCommentBack(false)
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/nonImportedCompletion.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/nonImportedCompletion.kt
new file mode 100644
index 0000000..ae012e9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/nonImportedCompletion.kt
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.resolve.lang.java.findTypes
+import org.jetbrains.kotlin.hints.fixes.autoImport
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.ElementKind
+import org.netbeans.modules.csl.api.HtmlFormatter
+import org.netbeans.modules.csl.spi.DefaultCompletionProposal
+import org.jetbrains.kotlin.utils.KotlinImageProvider
+import org.jetbrains.kotlin.search.PublicFunctionsVisitor
+import javax.swing.text.Document
+
+fun generateNonImportedCompletionProposals(identifierPart: String,
+ ktFile: KtFile, expression: KtSimpleNameExpression,
+ project: Project, idenOffset: Int) =
+ lookupNonImportedTypes(expression, identifierPart, ktFile, project, idenOffset)
+ .toMutableList()
+ .apply { addAll(lookupNonImportedFunctions(identifierPart, project, idenOffset)) }
+
+private fun lookupNonImportedTypes(simpleNameExpression: KtSimpleNameExpression,
+ identifierPart: String, ktFile: KtFile,
+ project: Project,
+ idenOffset: Int): List<NonImportedCompletionProposal> {
+ val callTypeAndReceiver = CallTypeAndReceiver.detect(simpleNameExpression)
+
+ if ((callTypeAndReceiver !is CallTypeAndReceiver.TYPE &&
+ callTypeAndReceiver !is CallTypeAndReceiver.DEFAULT) ||
+ callTypeAndReceiver.receiver != null) {
+ return emptyList()
+ }
+
+ val importsSet = ktFile.importDirectives.mapNotNullTo(hashSetOf()) { it.importedFqName?.asString() }
+
+ return project.findTypes(identifierPart)
+ .filter { it.qualifiedName !in importsSet }
+ .map { NonImportedCompletionProposal(identifierPart, it.qualifiedName, ElementKind.CLASS, idenOffset) }
+}
+
+private fun lookupNonImportedFunctions(identifierPart: String,
+ project: Project,
+ idenOffset: Int) = ProjectUtils.getSourceFiles(project)
+ .flatMap { ktFile ->
+ PublicFunctionsVisitor({ it.startsWith(identifierPart) }).let {
+ ktFile.acceptChildren(it)
+ it.publicFunctions
+ }
+ }
+ .map { NonImportedCompletionProposal(identifierPart, it, ElementKind.METHOD, idenOffset) }
+
+
+class NonImportedCompletionProposal(private val identifierPart: String,
+ val text: String,
+ private val elemKind: ElementKind,
+ private val idenOffset: Int) : DefaultCompletionProposal(), InsertableProposal {
+
+ override fun doInsert(document: Document) {
+ document.remove(idenOffset, identifierPart.length)
+ document.insertString(idenOffset, text.substringAfterLast("."), null)
+ autoImport(text, document)
+ }
+
+ override fun getElement() = null
+
+ override fun getIcon() = when (elemKind) {
+ ElementKind.CLASS -> KotlinImageProvider.typeImage
+ ElementKind.METHOD -> KotlinImageProvider.functionImage
+ else -> null
+ }
+
+ override fun getAnchorOffset() = idenOffset
+
+ override fun getKind() = elemKind
+
+ override fun getName() = text
+
+ override fun getSortText() = text
+
+ override fun getSortPrioOverride() = 50
+
+ override fun isSmart() = false
+
+ override fun getInsertPrefix() = text
+
+ override fun getRhsHtml(hf: HtmlFormatter?) = ""
+
+ override fun getLhsHtml(hf: HtmlFormatter?) = "<i>${text.substringAfterLast(".")}</i> (${text.substringBeforeLast(".")})"
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/positionFilters.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/positionFilters.kt
new file mode 100644
index 0000000..c8e6461
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/completion/positionFilters.kt
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.completion
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiNamedElement
+import com.intellij.psi.PsiType
+import com.intellij.psi.filters.ElementFilter
+import com.intellij.psi.filters.position.PositionElementFilter
+
+class TextFilter(val value: String) : ElementFilter {
+ override fun isAcceptable(element: Any?, context: PsiElement?): Boolean {
+ if (element == null) return false
+ return getTextByElement(element) == value
+ }
+
+ override fun isClassAcceptable(hintClass: Class<*>): Boolean = true
+
+ private fun getTextByElement(element: Any): String? = when (element) {
+ is PsiType -> element.presentableText
+ is PsiNamedElement -> element.name
+ is PsiElement -> element.text
+ else -> null
+ }
+}
+
+class LeftNeighbour(filter: ElementFilter) : PositionElementFilter() {
+ init {
+ setFilter(filter)
+ }
+
+ override fun isAcceptable(element: Any?, context: PsiElement?): Boolean {
+ if (element !is PsiElement) return false
+
+ val previous = element.searchNonSpaceNonCommentBack()
+ return if (previous != null) filter.isAcceptable(previous, context) else false
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinDebugUtils.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinDebugUtils.java
new file mode 100644
index 0000000..aeae699
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinDebugUtils.java
@@ -0,0 +1,262 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.debugger;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import javax.swing.text.StyledDocument;
+import kotlin.Pair;
+import org.jetbrains.kotlin.builder.KotlinPsiManager;
+import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider;
+import org.jetbrains.kotlin.name.FqName;
+import org.jetbrains.kotlin.psi.KtClass;
+import org.jetbrains.kotlin.psi.KtDeclaration;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.psi.KtFunction;
+import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.api.debugger.Breakpoint;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.jpda.FieldBreakpoint;
+import org.netbeans.api.debugger.jpda.JPDABreakpoint;
+import org.netbeans.api.debugger.jpda.LineBreakpoint;
+import org.netbeans.api.debugger.jpda.MethodBreakpoint;
+import org.netbeans.modules.debugger.jpda.EditorContextBridge;
+import org.netbeans.spi.debugger.jpda.EditorContext;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.text.NbDocument;
+import org.openide.util.Exceptions;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+class KotlinDebugUtils {
+
+ private static KtDeclaration findDeclarationBeforeEndOffset(KtFile ktFile, StyledDocument doc, int startOffset, int endOffset, int initialStartOffset) {
+ PsiElement element = null;
+ if (startOffset > endOffset) {
+ return null;
+ }
+
+ element = ktFile.findElementAt(startOffset);
+ if (element == null) {
+ return null;
+ }
+
+ KtDeclaration declaration = PsiTreeUtil.getNonStrictParentOfType(element, KtDeclaration.class);
+
+ if (declaration != null && declaration instanceof KtFunction
+ && declaration.getTextRange().getStartOffset() < endOffset
+ && declaration.getTextRange().getStartOffset() > initialStartOffset) {
+ return declaration;
+ }
+
+ return findDeclarationBeforeEndOffset(ktFile, doc, element.getTextRange().getEndOffset() + 1, endOffset, initialStartOffset);
+ }
+
+ private static KtDeclaration findDeclarationAtLine(KtFile ktFile, StyledDocument doc, int line) {
+ int lineNumber = NbDocument.findLineNumber(doc, doc.getLength());
+ if (lineNumber == line - 1) {
+ return null;
+ }
+ int startOffset = NbDocument.findLineOffset(doc, line - 1);
+ int endOffset = NbDocument.findLineOffset(doc, line);
+
+ return findDeclarationBeforeEndOffset(ktFile, doc, startOffset, endOffset, startOffset);
+ }
+
+ private static FileObject getFileObjectFromJar(URL url){
+ String separator = "!/";
+ String[] pathParts = url.getPath().split(separator);
+ if (pathParts.length < 2){
+ return null;
+ }
+
+ URL archiveFile = FileUtil.getArchiveFile(url);
+ File jar = FileUtil.archiveOrDirForURL(archiveFile);
+ jar = jar.getAbsoluteFile();
+
+ FileObject fob = FileUtil.toFileObject(jar);
+ fob = FileUtil.getArchiveRoot(fob);
+
+ String[] internalPathParts = pathParts[1].split("/");
+ for (String pathPart : internalPathParts){
+ fob = fob.getFileObject(pathPart);
+ }
+ return fob;
+ }
+
+ private static FileObject getFileFromUrlString(String urlStr) {
+ try {
+ URL url = new URL(urlStr);
+ if (url.getProtocol().equals("jar")) {
+ return getFileObjectFromJar(url);
+ }
+ File file = Utilities.toFile(url.toURI());
+ if (file == null) {
+ return null;
+ }
+ return FileUtil.toFileObject(file);
+ } catch (MalformedURLException | URISyntaxException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return null;
+ }
+
+ static Pair<String, String> getFunctionNameAndContainingClass(String urlStr, int lineNumber) {
+ String name;
+ String classFqName;
+
+ try {
+ FileObject fo = getFileFromUrlString(urlStr);
+ if (fo == null) {
+ return null;
+ }
+ KtFile ktFile = KotlinPsiManager.INSTANCE.getParsedFile(fo);
+ StyledDocument doc = ProjectUtils.getDocumentFromFileObject(fo);
+ KtDeclaration declaration = findDeclarationAtLine(ktFile, doc, lineNumber);
+ if (declaration == null) {
+ return null;
+ }
+ name = declaration.getName();
+ KtClass containingClass = KtPsiUtilKt.containingClass(declaration);
+ if (containingClass != null) {
+ FqName fqName = containingClass.getFqName();
+ if (fqName != null) {
+ classFqName = fqName.asString();
+ } else {
+ classFqName = NoResolveFileClassesProvider.INSTANCE.getFileClassInfo(ktFile).getFacadeClassFqName().toString();
+ }
+ } else {
+ classFqName = NoResolveFileClassesProvider.INSTANCE.getFileClassInfo(ktFile).getFacadeClassFqName().toString();
+ }
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ return null;
+ }
+
+ return new Pair<>(classFqName, name);
+ }
+
+ static String getClassFqName(String urlStr, int line) {
+ String classFqName = null;
+ try {
+ FileObject fo = getFileFromUrlString(urlStr);
+ if (fo == null) return null;
+ KtFile ktFile = KotlinPsiManager.INSTANCE.getParsedFile(fo);
+ classFqName = NoResolveFileClassesProvider.INSTANCE.getFileClassInfo(ktFile).getFacadeClassFqName().toString();
+ if (ktFile == null) return classFqName;
+
+ StyledDocument doc = ProjectUtils.getDocumentFromFileObject(fo);
+ int offset = NbDocument.findLineOffset(doc, line - 1);
+ PsiElement psi = ktFile.findElementAt(offset);
+ if (psi == null) return classFqName;
+ KtDeclaration declaration = PsiTreeUtil.getNonStrictParentOfType(psi, KtDeclaration.class);
+ if (declaration == null) return classFqName;
+
+ KtClass containingClass = KtPsiUtilKt.containingClass(declaration);
+ if (containingClass != null) {
+ FqName fqName = containingClass.getFqName();
+ if (fqName != null) {
+ classFqName = fqName.asString();
+ }
+ }
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return classFqName;
+ }
+
+ static Object annotate(JPDABreakpoint b, String url, int line) {
+ String annotationType;
+ if (b instanceof FieldBreakpoint) {
+ annotationType = b.isEnabled()
+ ? EditorContext.FIELD_BREAKPOINT_ANNOTATION_TYPE
+ : EditorContext.DISABLED_FIELD_BREAKPOINT_ANNOTATION_TYPE;
+ } else if (b instanceof MethodBreakpoint) {
+ annotationType = b.isEnabled()
+ ? EditorContext.METHOD_BREAKPOINT_ANNOTATION_TYPE
+ : EditorContext.DISABLED_METHOD_BREAKPOINT_ANNOTATION_TYPE;
+ } else {
+ return null;
+ }
+
+ return EditorContextBridge.getContext().annotate(url, line, annotationType, null);
+ }
+
+ static MethodBreakpoint findMethodBreakpoint(DebuggerManager manager, String className, String functionName) {
+ Breakpoint[] breakpoints = manager.getBreakpoints();
+ for (Breakpoint breakpoint : breakpoints) {
+ if (!(breakpoint instanceof MethodBreakpoint)) {
+ continue;
+ }
+ MethodBreakpoint methodBreakpoint = (MethodBreakpoint) breakpoint;
+ if (methodBreakpoint.getMethodName().equals(functionName)) {
+ String[] classFilters = methodBreakpoint.getClassFilters();
+ for (String classFilter : classFilters) {
+ if (match(classFilter, className)) {
+ return methodBreakpoint;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static boolean match(String name, String pattern) {
+ if (pattern.startsWith("*")) {
+ return name.endsWith(pattern.substring(1));
+ } else if (pattern.endsWith("*")) {
+ return name.startsWith(
+ pattern.substring(0, pattern.length() - 1)
+ );
+ }
+
+ return name.equals(pattern);
+ }
+
+ static LineBreakpoint findBreakpoint(String url, int lineNumber) {
+ Breakpoint[] breakpoints = DebuggerManager.getDebuggerManager().getBreakpoints();
+ for (Breakpoint breakpoint : breakpoints) {
+ if (!(breakpoint instanceof LineBreakpoint)) {
+ continue;
+ }
+ LineBreakpoint lb = (LineBreakpoint) breakpoint;
+ if (!lb.getURL().equals(url)) {
+ continue;
+ }
+ if (lb.getLineNumber() == lineNumber) {
+ return lb;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinSourcePathProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinSourcePathProvider.java
new file mode 100644
index 0000000..4402334
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinSourcePathProvider.java
@@ -0,0 +1,149 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.debugger;
+
+import com.intellij.psi.util.PsiTreeUtil;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider;
+import org.jetbrains.kotlin.name.FqName;
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper;
+import org.jetbrains.kotlin.psi.KtClass;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ui.OpenProjects;
+import org.netbeans.modules.debugger.jpda.projects.SourcePathProviderImpl;
+import org.netbeans.spi.debugger.ContextProvider;
+import org.netbeans.spi.debugger.jpda.SourcePathProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinSourcePathProvider extends SourcePathProvider {
+
+ private final SourcePathProviderImpl impl;
+
+ public KotlinSourcePathProvider() {
+ impl = new SourcePathProviderImpl();
+ }
+
+ public KotlinSourcePathProvider(ContextProvider contextProvider) {
+ impl = new SourcePathProviderImpl(contextProvider);
+ }
+
+ @Override
+ public String getRelativePath(String url, char directorySeparator, boolean includeExtension) {
+ return impl.getRelativePath(url, directorySeparator, includeExtension);
+ }
+
+ private String getURLFromProject(Project project, String relativePath) {
+ List<KtFile> sourceFiles = ProjectUtils.getSourceFilesWithDependencies(project);
+ for (KtFile ktFile : sourceFiles) {
+ FqName packageFqName = ktFile.getPackageFqName();
+ String fqName = relativePath.replace("/", ".");
+ if (!fqName.startsWith(packageFqName.asString())) {
+ continue;
+ }
+ Collection<KtClass> classes = PsiTreeUtil.findChildrenOfType(ktFile, KtClass.class);
+ for (KtClass ktClass : classes) {
+ FqName ktClassFqName = ktClass.getFqName();
+ if (ktClassFqName == null) continue;
+ if (ktClassFqName.asString().equals(fqName)) {
+ String path = ktFile.getVirtualFile().getPath();
+ File file = new File(path);
+ FileObject fo = FileUtil.toFileObject(file);
+ return fo.toURL().toString();
+ }
+ }
+
+ String classFqName = NoResolveFileClassesProvider.INSTANCE.getFileClassInfo(ktFile).getFacadeClassFqName().toString();
+ if (classFqName.equals(fqName)) {
+ String path = ktFile.getVirtualFile().getPath();
+ File file = new File(path);
+ FileObject fo = FileUtil.toFileObject(file);
+ return fo.toURL().toString();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getURL(String relativePath, boolean global) {
+ Project project = null;
+ Set<FileObject> sourceRootsFO = impl.getSourceRootsFO();
+ for ( Project proj : OpenProjects.getDefault().getOpenProjects()) {
+ if (!KotlinProjectHelper.INSTANCE.checkProject(proj)) {
+ continue;
+ }
+
+ for (FileObject srcRoot : sourceRootsFO) {
+ String srcRootDir = srcRoot.getPath();
+ String projDir = proj.getProjectDirectory().getPath();
+ if (srcRootDir.startsWith(projDir)) {
+ project = proj;
+ break;
+ }
+ }
+
+ if (project != null) {
+ break;
+ }
+ }
+
+ String url = getURLFromProject(project, relativePath);
+ if (url != null) {
+ return url;
+ }
+
+ return impl.getURL(relativePath, global);
+ }
+
+ @Override
+ public String[] getSourceRoots() {
+ return impl.getSourceRoots();
+ }
+
+ @Override
+ public void setSourceRoots(String[] sourceRoots) {
+ impl.setSourceRoots(sourceRoots);
+ }
+
+ @Override
+ public String[] getOriginalSourceRoots() {
+ return impl.getOriginalSourceRoots();
+ }
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ impl.addPropertyChangeListener(l);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ impl.removePropertyChangeListener(l);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinToggleBreakpointAction.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinToggleBreakpointAction.java
new file mode 100644
index 0000000..73bf3da
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinToggleBreakpointAction.java
@@ -0,0 +1,69 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.debugger;
+
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.netbeans.api.debugger.ActionsManager;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionRegistration;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+@ActionID(id = "org.jetbrains.kotlin.debugger.KotlinToggleBreakpointAction", category = "Debug")
+@ActionRegistration(displayName = "KotlinBreakpoint", lazy = false)
+public class KotlinToggleBreakpointAction extends AbstractAction {
+
+ private static final String[] BREAKPOINT_ANNOTATION_TYPES = new String[] {
+ "Breakpoint_broken",
+ "Breakpoint",
+ "CondBreakpoint_broken",
+ "CondBreakpoint",
+ "DisabledBreakpoint",
+ "DisabledCondBreakpoint",
+ "ClassBreakpoint",
+ "DisabledClassBreakpoint",
+ "DisabledFieldBreakpoint",
+ "DisabledMethodBreakpoint",
+ "FieldBreakpoint",
+ "MethodBreakpoint",
+ };
+
+ private Object action;
+
+ public KotlinToggleBreakpointAction() {
+ super.setEnabled (true);
+ super.putValue("default-action", true);
+ super.putValue("supported-annotation-types", BREAKPOINT_ANNOTATION_TYPES);
+ super.putValue("default-action-excluded-annotation-types", BREAKPOINT_ANNOTATION_TYPES);
+ }
+
+ public Object getAction () {
+ return action;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ DebuggerManager.getDebuggerManager().getActionsManager().doAction(ActionsManager.ACTION_TOGGLE_BREAKPOINT);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinToggleBreakpointActionProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinToggleBreakpointActionProvider.java
new file mode 100644
index 0000000..7a27903
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/debugger/KotlinToggleBreakpointActionProvider.java
@@ -0,0 +1,208 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.debugger;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.SwingUtilities;
+import kotlin.Pair;
+import org.netbeans.api.debugger.ActionsManager;
+import org.netbeans.api.debugger.Breakpoint;
+import org.netbeans.api.debugger.DebuggerManager;
+import org.netbeans.api.debugger.jpda.JPDABreakpoint;
+import org.netbeans.api.debugger.jpda.JPDADebugger;
+import org.netbeans.api.debugger.jpda.LineBreakpoint;
+import org.netbeans.api.debugger.jpda.MethodBreakpoint;
+import org.netbeans.api.debugger.jpda.event.JPDABreakpointEvent;
+import org.netbeans.api.debugger.jpda.event.JPDABreakpointListener;
+import org.netbeans.modules.debugger.jpda.EditorContextBridge;
+import org.netbeans.spi.debugger.ActionsProvider;
+import org.netbeans.spi.debugger.ActionsProviderSupport;
+import org.netbeans.spi.debugger.ContextProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.URLMapper;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+@ActionsProvider.Registrations({
+ @ActionsProvider.Registration(path="", actions={ "toggleBreakpoint" }, activateForMIMETypes={ "text/x-kt" }),
+ @ActionsProvider.Registration(path="netbeans-JPDASession", actions={ "toggleBreakpoint" }, activateForMIMETypes={ "text/x-kt" })
+})
+public class KotlinToggleBreakpointActionProvider extends ActionsProviderSupport
+ implements PropertyChangeListener {
+
+ private JPDADebugger debugger;
+ private Map<Breakpoint, Object> annotations = new HashMap<>();
+
+ public KotlinToggleBreakpointActionProvider() {
+ EditorContextBridge.getContext().
+ addPropertyChangeListener(KotlinToggleBreakpointActionProvider.this);
+ enableAllActions();
+ }
+
+ public KotlinToggleBreakpointActionProvider(ContextProvider lookupProvider) {
+ debugger = lookupProvider.lookupFirst(null, JPDADebugger.class);
+ debugger.addPropertyChangeListener(JPDADebugger.PROP_STATE,
+ KotlinToggleBreakpointActionProvider.this);
+ enableAllActions();
+ EditorContextBridge.getContext().
+ addPropertyChangeListener(KotlinToggleBreakpointActionProvider.this);
+ }
+
+ private void destroy() {
+ debugger.removePropertyChangeListener(JPDADebugger.PROP_STATE, this);
+ EditorContextBridge.getContext().removePropertyChangeListener(this);
+ }
+
+ @Override
+ public boolean isEnabled(Object action) {
+ return true;
+ }
+
+ @Override
+ public void doAction(Object o) {
+ DebuggerManager manager = DebuggerManager.getDebuggerManager();
+ JPDABreakpoint breakpoint;
+
+ final int lineNumber = EditorContextBridge.getContext().getCurrentLineNumber();
+ if (lineNumber < 0) {
+ return;
+ }
+ final String urlStr = EditorContextBridge.getContext().getCurrentURL();
+
+ if ("".equals(urlStr.trim())) {
+ return;
+ }
+
+ Pair<String, String> functionNameAndClassName = KotlinDebugUtils.getFunctionNameAndContainingClass(urlStr, lineNumber);
+ if (functionNameAndClassName != null) {
+ MethodBreakpoint mBr = KotlinDebugUtils.findMethodBreakpoint(manager, functionNameAndClassName.getFirst(),
+ functionNameAndClassName.getSecond());
+ if (mBr != null) {
+ manager.removeBreakpoint(mBr);
+ Object annotation = annotations.get(mBr);
+ if (annotation != null) {
+ EditorContextBridge.getContext().removeAnnotation(annotation);
+ }
+ return;
+ }
+ breakpoint = MethodBreakpoint.create(functionNameAndClassName.getFirst(),
+ functionNameAndClassName.getSecond());
+ } else {
+ LineBreakpoint lBr = KotlinDebugUtils.findBreakpoint(urlStr, lineNumber);
+ if (lBr != null) {
+ manager.removeBreakpoint(lBr);
+ Object annotation = annotations.get(lBr);
+ if (annotation != null) {
+ EditorContextBridge.getContext().removeAnnotation(annotation);
+ }
+ return;
+ }
+ breakpoint = LineBreakpoint.create(urlStr, lineNumber);
+ String className = KotlinDebugUtils.getClassFqName(urlStr, lineNumber);
+ if (className == null) {
+ className = "";
+ }
+ ((LineBreakpoint) breakpoint).setPreferredClassName(className);
+ }
+
+ breakpoint.addJPDABreakpointListener(new JPDABreakpointListener() {
+ @Override
+ public void breakpointReached(final JPDABreakpointEvent event) {
+ SwingUtilities.invokeLater(new Runnable(){
+ @Override
+ public void run() {
+ EditorContextBridge.getContext().showSource(urlStr, lineNumber, null);
+ }
+ });
+ }
+ });
+
+ Object annotation = KotlinDebugUtils.annotate(breakpoint, urlStr, lineNumber);
+ if (annotation != null) {
+ annotations.put(breakpoint, annotation);
+ }
+ manager.addBreakpoint(breakpoint);
+ }
+
+ @Override
+ public Set getActions() {
+ return Collections.singleton(ActionsManager.ACTION_TOGGLE_BREAKPOINT);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ String url = EditorContextBridge.getContext().getCurrentURL();
+ FileObject fo;
+ try {
+ fo = URLMapper.findFileObject(new URL(url));
+ } catch (MalformedURLException ex) {
+ fo = null;
+ }
+ setEnabled(ActionsManager.ACTION_TOGGLE_BREAKPOINT,
+ (EditorContextBridge.getContext().getCurrentLineNumber() >= 0) &&
+ (fo != null && "text/x-kt".equals(fo.getMIMEType())));
+ if (debugger != null && debugger.getState() == JPDADebugger.STATE_DISCONNECTED) {
+ destroy();
+ }
+ }
+
+ @Override
+ public void postAction(final Object action, final Runnable actionPerformedNotifier) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ doAction(action);
+// actionPerformedNotifier.run();
+ }
+ });
+ }
+
+ private void enableAllActions() {
+ setEnabled(ActionsManager.ACTION_TOGGLE_BREAKPOINT, true);
+ setEnabled(ActionsManager.ACTION_CONTINUE, true);
+ setEnabled(ActionsManager.ACTION_EVALUATE, true);
+ setEnabled(ActionsManager.ACTION_FIX, true);
+ setEnabled(ActionsManager.ACTION_KILL, true);
+ setEnabled(ActionsManager.ACTION_MAKE_CALLEE_CURRENT, true);
+ setEnabled(ActionsManager.ACTION_NEW_WATCH, true);
+ setEnabled(ActionsManager.ACTION_MAKE_CALLER_CURRENT, true);
+ setEnabled(ActionsManager.ACTION_PAUSE, true);
+ setEnabled(ActionsManager.ACTION_POP_TOPMOST_CALL, true);
+ setEnabled(ActionsManager.ACTION_RESTART, true);
+ setEnabled(ActionsManager.ACTION_RUN_INTO_METHOD, true);
+ setEnabled(ActionsManager.ACTION_RUN_TO_CURSOR, true);
+ setEnabled(ActionsManager.ACTION_START, true);
+ setEnabled(ActionsManager.ACTION_STEP_INTO, true);
+ setEnabled(ActionsManager.ACTION_STEP_OPERATION, true);
+ setEnabled(ActionsManager.ACTION_STEP_OUT, true);
+ setEnabled(ActionsManager.ACTION_STEP_OVER, true);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/bracesmatcher/KotlinBracesMatcherFactory.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/bracesmatcher/KotlinBracesMatcherFactory.java
new file mode 100644
index 0000000..b0eeb30
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/bracesmatcher/KotlinBracesMatcherFactory.java
@@ -0,0 +1,34 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.diagnostics.netbeans.bracesmatcher;
+
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.spi.editor.bracesmatching.BracesMatcher;
+import org.netbeans.spi.editor.bracesmatching.BracesMatcherFactory;
+import org.netbeans.spi.editor.bracesmatching.MatcherContext;
+import org.netbeans.spi.editor.bracesmatching.support.BracesMatcherSupport;
+
+@MimeRegistration(mimeType="text/x-kt",service=BracesMatcherFactory.class)
+public class KotlinBracesMatcherFactory implements BracesMatcherFactory {
+
+ @Override
+ public BracesMatcher createMatcher(MatcherContext context) {
+ return BracesMatcherSupport.defaultMatcher(context, -1, -1);
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/KotlinParser.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/KotlinParser.kt
new file mode 100644
index 0000000..df70687
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/KotlinParser.kt
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.diagnostics.netbeans.parser
+
+import javax.swing.event.ChangeListener
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.isScanning
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.psi.KtFile
+import org.netbeans.api.java.source.SourceUtils
+import org.netbeans.api.project.Project
+import org.netbeans.modules.parsing.api.*
+import org.netbeans.modules.parsing.spi.*
+
+class KotlinParser : Parser() {
+
+ companion object {
+ var file: KtFile? = null
+ private set
+
+ var project: Project? = null
+ private set
+
+ var analysisResult: AnalysisResultWithProvider? = null
+
+ @JvmStatic fun getAnalysisResult(ktFile: KtFile,
+ proj: Project) = if (ktFile upToDate file) analysisResult else analyze(ktFile, proj)
+
+ private fun analyze(ktFile: KtFile,
+ proj: Project): AnalysisResultWithProvider? = KotlinAnalyzer.analyzeFile(proj, ktFile)
+ .also {
+ project = proj
+ file = ktFile
+ analysisResult = it
+ }
+
+ private infix fun KtFile.upToDate(ktFile: KtFile?) =
+ virtualFile.path == ktFile?.virtualFile?.path && text == ktFile.text
+
+ }
+
+ private lateinit var snapshot: Snapshot
+ private var cancel = false
+
+ override fun parse(snapshot: Snapshot, task: Task, event: SourceModificationEvent) {
+ this.snapshot = snapshot
+ cancel = false
+
+ if (SourceUtils.isScanInProgress()) return
+
+ val project = ProjectUtils.getKotlinProjectForFileObject(snapshot.source.fileObject)
+ if (project.isScanning()) return
+ if (cancel) return
+
+ val ktFile = ProjectUtils.getKtFile(snapshot.text.toString(), snapshot.source.fileObject)
+
+ getAnalysisResult(ktFile, project)
+ }
+
+ override fun getResult(task: Task): Result? {
+ val project = project ?: return null
+ val ktFile = if (snapshot.source.fileObject.path == file?.virtualFile?.path) file else null
+ ktFile ?: return null
+ val result = getAnalysisResult(ktFile, project) ?: return null
+
+ return KotlinParserResult(snapshot, result, ktFile, snapshot.source.fileObject, project)
+ }
+
+ override fun addChangeListener(changeListener: ChangeListener) {}
+ override fun removeChangeListener(changeListener: ChangeListener) {}
+
+ override fun cancel(reason: CancelReason, event: SourceModificationEvent?) {
+ cancel = true
+ KotlinLogger.INSTANCE.logInfo("Parser cancel ${reason.name}")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/KotlinParserResult.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/KotlinParserResult.kt
new file mode 100644
index 0000000..0d3bd92
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/KotlinParserResult.kt
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.diagnostics.netbeans.parser
+
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.resolve.AnalyzingUtils
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.psi.KtFile
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.Error
+import org.netbeans.modules.csl.spi.ParserResult
+import org.netbeans.modules.parsing.api.Snapshot
+import org.openide.filesystems.FileObject
+
+class KotlinParserResult(snapshot: Snapshot?,
+ val analysisResult: AnalysisResultWithProvider?,
+ val ktFile: KtFile,
+ val file: FileObject,
+ val project: Project) : ParserResult(snapshot) {
+
+ override fun invalidate() {}
+
+ override fun getDiagnostics() = arrayListOf<Error>().apply {
+ if (analysisResult != null) {
+ addAll(
+ analysisResult.analysisResult.bindingContext.diagnostics.all()
+ .filter { it.factory != Errors.DEPRECATION }
+ .map { KotlinError(it, file) }
+ )
+ }
+ addAll(
+ AnalyzingUtils.getSyntaxErrorRanges(ktFile)
+ .map { KotlinSyntaxError(it, file) }
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/kotlinErrors.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/kotlinErrors.kt
new file mode 100644
index 0000000..4a399bd
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/parser/kotlinErrors.kt
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.diagnostics.netbeans.parser
+
+import org.jetbrains.kotlin.diagnostics.Diagnostic
+import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
+import org.netbeans.modules.csl.api.Error.Badging
+import org.netbeans.modules.csl.api.Severity
+import org.openide.filesystems.FileObject
+import com.intellij.psi.PsiErrorElement
+import org.jetbrains.kotlin.diagnostics.Severity as KotlinSeverity
+
+class KotlinError(val diagnostic: Diagnostic, val fileObject: FileObject) : Badging {
+
+ val psi = diagnostic.psiElement
+
+ override fun toString() = diagnostic.toString()
+
+ override fun showExplorerBadge() = diagnostic.severity == KotlinSeverity.ERROR
+
+ override fun getDisplayName() = DefaultErrorMessages.render(diagnostic)
+
+ override fun getDescription() = ""
+
+ override fun getKey() = ""
+
+ override fun getFile() = fileObject
+
+ override fun getStartPosition() = diagnostic.textRanges[0].startOffset
+
+ override fun getEndPosition() = diagnostic.textRanges[0].endOffset
+
+ override fun isLineError() = startPosition - endPosition == 0
+
+ override fun getSeverity() = when (diagnostic.severity) {
+ KotlinSeverity.ERROR -> Severity.ERROR
+ KotlinSeverity.WARNING -> Severity.WARNING
+ KotlinSeverity.INFO -> Severity.INFO
+ else -> null
+ }
+
+
+ override fun getParameters() = null
+}
+
+class KotlinSyntaxError(private val psiError: PsiErrorElement, val fileObject: FileObject) : Badging {
+ override fun showExplorerBadge() = true
+
+ override fun getDisplayName(): String = psiError.errorDescription ?: ""
+
+ override fun getDescription() = ""
+
+ override fun getKey() = ""
+
+ override fun getFile() = fileObject
+
+ override fun getStartPosition() = psiError.textRange.startOffset
+
+ override fun getEndPosition() = psiError.textRange.endOffset
+
+ override fun isLineError() = false
+
+ override fun getSeverity() = Severity.ERROR
+
+ override fun getParameters() = null
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/textinterceptor/KotlinKeystrokeHandler.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/textinterceptor/KotlinKeystrokeHandler.kt
new file mode 100644
index 0000000..00bf552
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/diagnostics/netbeans/textinterceptor/KotlinKeystrokeHandler.kt
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.diagnostics.netbeans.textinterceptor
+
+import javax.swing.text.Document
+import javax.swing.text.JTextComponent
+import org.netbeans.modules.csl.api.KeystrokeHandler
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.csl.spi.ParserResult
+
+class KotlinKeystrokeHandler : KeystrokeHandler {
+
+ private fun checkNextChar(doc: Document, caretOffset: Int, ch: String,
+ target: JTextComponent): Boolean {
+ if (doc.getText(caretOffset, 1) == ch) {
+ target.caretPosition = caretOffset + 1
+ return true
+ }
+ return false
+ }
+
+ private fun insert(doc: Document, caretOffset: Int, ch: String,
+ target: JTextComponent): Boolean {
+ doc.insertString(caretOffset + 1, ch, null)
+ target.caretPosition = caretOffset + 1
+ return false
+ }
+
+ override fun beforeCharInserted(doc: Document, caretOffset: Int,
+ target: JTextComponent, ch: Char): Boolean {
+ if (ch !in arrayOf('"', '\'', ')', '}',']')) return false
+
+ return checkNextChar(doc, caretOffset, ch.toString(), target)
+ }
+
+ override fun afterCharInserted(doc: Document, caretOffset: Int,
+ target: JTextComponent, ch: Char): Boolean = when(ch) {
+ '(' -> insert(doc, caretOffset, ")", target)
+ '{' -> insert(doc, caretOffset, "}", target)
+ '[' -> insert(doc, caretOffset, "]", target)
+ '"' -> insert(doc, caretOffset, "\"", target)
+ '\'' -> insert(doc, caretOffset, "'", target)
+ else -> false
+ }
+
+ override fun charBackspaced(doc: Document, caretOffset: Int, target: JTextComponent, ch: Char) = false
+ override fun beforeBreak(doc: Document, caretOffset: Int, target: JTextComponent) = -1
+ override fun findMatching(doc: Document, caretOffset: Int) = OffsetRange.NONE
+ override fun findLogicalRanges(info: ParserResult, caretOffset: Int) = emptyList<OffsetRange>()
+ override fun getNextWordOffset(doc: Document, caretOffset: Int, reverse: Boolean) = -1
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtDataObject.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtDataObject.java
new file mode 100644
index 0000000..c806702
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtDataObject.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file;
+
+import java.io.IOException;
+import org.netbeans.core.spi.multiview.MultiViewElement;
+import org.netbeans.core.spi.multiview.text.MultiViewEditorElement;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.MIMEResolver;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.MultiDataObject;
+import org.openide.loaders.MultiFileLoader;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.TopComponent;
+
+@Messages({
+ "LBL_Kt_LOADER=Files of Kt"
+})
+@MIMEResolver.ExtensionRegistration(
+ displayName = "#LBL_Kt_LOADER",
+ mimeType = "text/x-kt",
+ extension = {"kt", "KT"}
+)
+@DataObject.Registration(
+ mimeType = "text/x-kt",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ displayName = "#LBL_Kt_LOADER",
+ position = 300
+)
+@ActionReferences({
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.OpenAction"),
+ position = 100,
+ separatorAfter = 200
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "Edit", id = "org.openide.actions.CutAction"),
+ position = 300
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "Edit", id = "org.openide.actions.CopyAction"),
+ position = 400,
+ separatorAfter = 500
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"),
+ position = 600
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.RenameAction"),
+ position = 700,
+ separatorAfter = 800
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"),
+ position = 900,
+ separatorAfter = 1000
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"),
+ position = 1100,
+ separatorAfter = 1200
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.ToolsAction"),
+ position = 1300
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-kt/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"),
+ position = 1400
+ )
+})
+public class KtDataObject extends MultiDataObject {
+
+ public KtDataObject(final FileObject file, MultiFileLoader loader) throws IOException {
+ super(file, loader);
+ registerEditor("text/x-kt", true);
+ }
+
+ @Override
+ protected int associateLookup() {
+ return 1;
+ }
+
+ @MultiViewElement.Registration(
+ displayName = "#LBL_Kt_EDITOR",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ mimeType = "text/x-kt",
+ persistenceType = TopComponent.PERSISTENCE_ONLY_OPENED,
+ preferredID = "Kt",
+ position = 1000
+ )
+ @Messages("LBL_Kt_EDITOR=Source")
+ public static MultiViewEditorElement createEditor(Lookup lkp) {
+ return new MultiViewEditorElement(lkp);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtVisualElement.form b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtVisualElement.form
new file mode 100644
index 0000000..5f3eab1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtVisualElement.form
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ </AuxValues>
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <EmptySpace min="0" pref="400" max="32767" attributes="0"/>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <EmptySpace min="0" pref="300" max="32767" attributes="0"/>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+</Form>
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtVisualElement.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtVisualElement.java
new file mode 100644
index 0000000..9ae0a41
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/KtVisualElement.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JToolBar;
+import org.netbeans.core.spi.multiview.CloseOperationState;
+import org.netbeans.core.spi.multiview.MultiViewElement;
+import org.netbeans.core.spi.multiview.MultiViewElementCallback;
+import org.openide.awt.UndoRedo;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.TopComponent;
+
+@MultiViewElement.Registration(
+ displayName = "#LBL_Kt_VISUAL",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ mimeType = "text/x-kt",
+ persistenceType = TopComponent.PERSISTENCE_NEVER,
+ preferredID = "KtVisual",
+ position = 2000
+)
+@Messages("LBL_Kt_VISUAL=Visual")
+public final class KtVisualElement extends JPanel implements MultiViewElement {
+
+ private final KtDataObject obj;
+ private final JToolBar toolbar = new JToolBar();
+ private transient MultiViewElementCallback callback;
+
+ public KtVisualElement(Lookup lkp) {
+ obj = lkp.lookup(KtDataObject.class);
+ assert obj != null;
+ initComponents();
+ }
+
+ @Override
+ public String getName() {
+ return "KtVisualElement";
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 400, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 300, Short.MAX_VALUE)
+ );
+ }// </editor-fold>//GEN-END:initComponents
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ // End of variables declaration//GEN-END:variables
+ @Override
+ public JComponent getVisualRepresentation() {
+ return this;
+ }
+
+ @Override
+ public JComponent getToolbarRepresentation() {
+ return toolbar;
+ }
+
+ @Override
+ public Action[] getActions() {
+ return new Action[0];
+ }
+
+ @Override
+ public Lookup getLookup() {
+ return obj.getLookup();
+ }
+
+ @Override
+ public void componentOpened() {
+ }
+
+ @Override
+ public void componentClosed() {
+ }
+
+ @Override
+ public void componentShowing() {
+ }
+
+ @Override
+ public void componentHidden() {
+ }
+
+ @Override
+ public void componentActivated() {
+ }
+
+ @Override
+ public void componentDeactivated() {
+ }
+
+ @Override
+ public UndoRedo getUndoRedo() {
+ return UndoRedo.NONE;
+ }
+
+ @Override
+ public void setMultiViewCallback(MultiViewElementCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public CloseOperationState canCloseElement() {
+ return CloseOperationState.STATE_OK;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtClassWizardIterator.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtClassWizardIterator.java
new file mode 100644
index 0000000..af121228
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtClassWizardIterator.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates;
+
+import org.jetbrains.kotlin.file.templates.defaultwizard.KtDefaultWizardIterator;
+import org.netbeans.api.templates.TemplateRegistration;
+
+@TemplateRegistration(folder = "Kotlin",
+ displayName = "Kotlin class",
+ content = "class.kt",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ description = "ktClass.html",
+ scriptEngine="freemarker")
+public final class KtClassWizardIterator extends KtDefaultWizardIterator {
+ public KtClassWizardIterator() {
+ super("Class");
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtEnumWizardIterator.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtEnumWizardIterator.java
new file mode 100644
index 0000000..afe94d5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtEnumWizardIterator.java
@@ -0,0 +1,32 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.file.templates;
+
+import org.jetbrains.kotlin.file.templates.defaultwizard.KtDefaultWizardIterator;
+import org.netbeans.api.templates.TemplateRegistration;
+
+@TemplateRegistration(folder = "Kotlin",
+ displayName = "Kotlin enum",
+ content = "enum.kt",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ description = "ktEnum.html",
+ scriptEngine="freemarker")
+public class KtEnumWizardIterator extends KtDefaultWizardIterator {
+ public KtEnumWizardIterator() {
+ super("Enum");
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtInterfaceWizardIterator.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtInterfaceWizardIterator.java
new file mode 100644
index 0000000..3c20d87
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtInterfaceWizardIterator.java
@@ -0,0 +1,32 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.file.templates;
+
+import org.jetbrains.kotlin.file.templates.defaultwizard.KtDefaultWizardIterator;
+import org.netbeans.api.templates.TemplateRegistration;
+
+@TemplateRegistration(folder = "Kotlin",
+ displayName = "Kotlin interface",
+ content = "interface.kt",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ description = "ktInterface.html",
+ scriptEngine="freemarker")
+public class KtInterfaceWizardIterator extends KtDefaultWizardIterator {
+ public KtInterfaceWizardIterator() {
+ super("Interface");
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtObjectWizardIterator.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtObjectWizardIterator.java
new file mode 100644
index 0000000..cf7f56f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtObjectWizardIterator.java
@@ -0,0 +1,32 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.file.templates;
+
+import org.jetbrains.kotlin.file.templates.defaultwizard.KtDefaultWizardIterator;
+import org.netbeans.api.templates.TemplateRegistration;
+
+@TemplateRegistration(folder = "Kotlin",
+ displayName = "Kotlin object",
+ content = "object.kt",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ description = "ktObject.html",
+ scriptEngine="freemarker")
+public class KtObjectWizardIterator extends KtDefaultWizardIterator {
+ public KtObjectWizardIterator() {
+ super("Object");
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtWizardIterator.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtWizardIterator.java
new file mode 100644
index 0000000..b887aac
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/KtWizardIterator.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates;
+
+import org.jetbrains.kotlin.file.templates.defaultwizard.KtDefaultWizardIterator;
+import org.netbeans.api.templates.TemplateRegistration;
+import org.openide.util.NbBundle.Messages;
+
+@TemplateRegistration(folder = "Kotlin",
+ displayName = "Kotlin file",
+ content = "content.kt",
+ iconBase = "org/jetbrains/kotlin/kt.png",
+ description = "kt.html",
+ scriptEngine="freemarker")
+@Messages("KtWizardIterator_displayName=Simple Kotlin File")
+public final class KtWizardIterator extends KtDefaultWizardIterator {
+ public KtWizardIterator() {
+ super("File");
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtDefaultWizardIterator.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtDefaultWizardIterator.java
new file mode 100644
index 0000000..5b2d6cd
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtDefaultWizardIterator.java
@@ -0,0 +1,249 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.file.templates.defaultwizard;
+
+import com.google.common.collect.Lists;
+import java.awt.Component;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import javax.swing.JComponent;
+import javax.swing.event.ChangeListener;
+import org.jetbrains.kotlin.file.templates.packagechooser.PackageChooser;
+import org.jetbrains.kotlin.file.templates.packagechooser.TargetChooserPanel;
+import org.netbeans.api.java.project.JavaProjectConstants;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.api.project.Sources;
+import org.netbeans.api.project.ui.OpenProjects;
+import org.netbeans.spi.project.ui.templates.support.Templates;
+import org.openide.WizardDescriptor;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataFolder;
+import org.openide.loaders.DataObject;
+import org.openide.util.HelpCtx;
+
+public abstract class KtDefaultWizardIterator implements WizardDescriptor.InstantiatingIterator<WizardDescriptor> {
+
+ private final String type;
+
+ public KtDefaultWizardIterator(String type) {
+ this.type = type;
+ }
+
+ private int index;
+
+ private WizardDescriptor wizard;
+ private TargetChooserPanel packageChooserPanel;
+ private List<WizardDescriptor.Panel<WizardDescriptor>> panels;
+
+ private List<WizardDescriptor.Panel<WizardDescriptor>> getPanels() {
+ if (panels == null) {
+ Project project = Templates.getProject(wizard);
+ SourceGroup[] groups;
+
+ if (project == null) {
+ List<SourceGroup> sourceGroups = Lists.newArrayList();
+
+ for (Project proj : OpenProjects.getDefault().getOpenProjects()) {
+ Sources sources = ProjectUtils.getSources(proj);
+ if (sources != null) {
+ sourceGroups.addAll(Arrays.asList(
+ sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)));
+ project = proj;
+ break;
+ }
+
+ }
+ groups = sourceGroups.toArray(new SourceGroup[sourceGroups.size()]);
+ } else {
+ Sources sources = ProjectUtils.getSources(project);
+ groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
+ }
+ packageChooserPanel = PackageChooser.createPackageChooser(project, groups, new KtWizardPanel(), type + " name");
+
+ panels = new ArrayList<>();
+ panels.add(packageChooserPanel);
+ String[] steps = createSteps();
+ for (int i = 0; i < panels.size(); i++) {
+ Component c = panels.get(i).getComponent();
+ if (steps[i] == null) {
+ // Default step name to component name of panel. Mainly
+ // useful for getting the name of the target chooser to
+ // appear in the list of steps.
+ steps[i] = c.getName();
+ }
+ if (c instanceof JComponent) { // assume Swing components
+ JComponent jc = (JComponent) c;
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
+ jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
+ jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
+ }
+ }
+ }
+
+ return panels;
+ }
+
+ @Override
+ public Set<?> instantiate() throws IOException {
+ Map<String, String> args = new HashMap<>();
+
+ String packageName = PackageChooser.pack;
+ args.put("package", packageName);
+
+ FileObject template = Templates.getTemplate(wizard);
+ DataObject dTemplate = DataObject.find(template);
+
+ FileObject dir = Templates.getTargetFolder(wizard);
+ DataFolder df = DataFolder.findFolder(dir);
+
+ String targetName = Templates.getTargetName(wizard);
+
+ DataObject dobj = dTemplate.createFromTemplate(df, targetName, args);
+
+ FileObject createdFile = dobj.getPrimaryFile();
+
+ return Collections.singleton(createdFile);
+ }
+
+ @Override
+ public void initialize(WizardDescriptor wizard) {
+ this.wizard = wizard;
+ }
+
+ @Override
+ public void uninitialize(WizardDescriptor wizard) {
+ panels = null;
+ }
+
+ @Override
+ public WizardDescriptor.Panel<WizardDescriptor> current() {
+ return getPanels().get(index);
+ }
+
+ @Override
+ public String name() {
+ return index + 1 + ". from " + getPanels().size();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < getPanels().size() - 1;
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return index > 0;
+ }
+
+ @Override
+ public void nextPanel() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ index++;
+ }
+
+ @Override
+ public void previousPanel() {
+ if (!hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+ index--;
+ }
+
+ // If nothing unusual changes in the middle of the wizard, simply:
+ @Override
+ public void addChangeListener(ChangeListener l) {
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener l) {
+ }
+ // If something changes dynamically (besides moving between panels), e.g.
+ // the number of panels changes in response to user input, then use
+ // ChangeSupport to implement add/removeChangeListener and call fireChange
+ // when needed
+
+ // You could safely ignore this method. Is is here to keep steps which were
+ // there before this wizard was instantiated. It should be better handled
+ // by NetBeans Wizard API itself rather than needed to be implemented by a
+ // client code.
+ private String[] createSteps() {
+ String[] beforeSteps = (String[]) wizard.getProperty("WizardPanel_contentData");
+ assert beforeSteps != null : "This wizard may only be used embedded in the template wizard";
+ String[] res = new String[(beforeSteps.length - 1) + panels.size()];
+ for (int i = 0; i < res.length; i++) {
+ if (i < (beforeSteps.length - 1)) {
+ res[i] = beforeSteps[i];
+ } else {
+ res[i] = panels.get(i - beforeSteps.length + 1).getComponent().getName();
+ }
+ }
+ return res;
+ }
+
+ private static class KtWizardPanel implements WizardDescriptor.Panel<WizardDescriptor> {
+
+ private KtVisualPanel1 component;
+
+ @Override
+ public KtVisualPanel1 getComponent() {
+ if (component == null) {
+ component = new KtVisualPanel1();
+ }
+ return component;
+ }
+
+ @Override
+ public HelpCtx getHelp() {
+ return HelpCtx.DEFAULT_HELP;
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener l) {
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener l) {
+ }
+
+ @Override
+ public void readSettings(WizardDescriptor wiz) {
+ }
+
+ @Override
+ public void storeSettings(WizardDescriptor wiz) {
+ }
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtVisualPanel1.form b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtVisualPanel1.form
new file mode 100644
index 0000000..5f3eab1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtVisualPanel1.form
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ </AuxValues>
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <EmptySpace min="0" pref="400" max="32767" attributes="0"/>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <EmptySpace min="0" pref="300" max="32767" attributes="0"/>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+</Form>
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtVisualPanel1.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtVisualPanel1.java
new file mode 100644
index 0000000..d17835c
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/defaultwizard/KtVisualPanel1.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates.defaultwizard;
+
+import javax.swing.JPanel;
+
+public final class KtVisualPanel1 extends JPanel {
+
+ /**
+ * Creates new form KtVisualPanel1
+ */
+ public KtVisualPanel1() {
+ initComponents();
+ }
+
+ @Override
+ public String getName() {
+ return "Step #1";
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 400, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 300, Short.MAX_VALUE)
+ );
+ }// </editor-fold>//GEN-END:initComponents
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/PackageChooser.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/PackageChooser.java
new file mode 100644
index 0000000..29578a6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/PackageChooser.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates.packagechooser;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.openide.WizardDescriptor;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class PackageChooser {
+
+ public static String pack = null;
+
+ public static TargetChooserPanel createPackageChooser(Project project, SourceGroup[] folders,
+ WizardDescriptor.Panel<WizardDescriptor> bottomPanel, String type) {
+ if (folders.length == 0) {
+ throw new IllegalArgumentException("No folders selected");
+ }
+ return new TargetChooserPanel(project, folders, bottomPanel, Type.FILE, false, type);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/TargetChooserPanel.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/TargetChooserPanel.java
new file mode 100644
index 0000000..1ab666a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/TargetChooserPanel.java
@@ -0,0 +1,446 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates.packagechooser;
+
+import java.awt.Component;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import org.netbeans.api.java.queries.SourceLevelQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.modules.java.project.ui.NewJavaFileWizardIterator;
+import org.netbeans.spi.project.ui.templates.support.Templates;
+import org.openide.WizardDescriptor;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.modules.SpecificationVersion;
+import org.openide.util.Exceptions;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class TargetChooserPanel implements WizardDescriptor.Panel<WizardDescriptor>, ChangeListener {
+
+private static final String FOLDER_TO_DELETE = "folderToDelete"; //NOI18N
+
+ private final SpecificationVersion JDK_14 = new SpecificationVersion ("1.4"); //NOI18N
+ private final List<ChangeListener> listeners = new ArrayList<ChangeListener>();
+ private TargetChooserPanelGUI gui;
+ private WizardDescriptor.Panel<WizardDescriptor> bottomPanel;
+ private WizardDescriptor wizard;
+
+ private Project project;
+ private SourceGroup folders[];
+ private final Type type;
+ private boolean isValidPackageRequired;
+ private final String fileType;
+
+ public TargetChooserPanel(Project project, SourceGroup folders[], WizardDescriptor.Panel<WizardDescriptor> bottomPanel, Type type, boolean isValidPackageRequired, String fileType) {
+ this.project = project;
+ this.folders = folders;
+ this.bottomPanel = bottomPanel;
+ this.type = type;
+ this.fileType = fileType;
+ if ( bottomPanel != null ) {
+ bottomPanel.addChangeListener( this );
+ }
+ this.isValidPackageRequired = isValidPackageRequired;
+ }
+
+ @Override
+ public Component getComponent() {
+ if (gui == null) {
+ gui = new TargetChooserPanelGUI( project, folders, bottomPanel == null ? null : bottomPanel.getComponent(), type, fileType);
+ gui.addChangeListener(this);
+ }
+ return gui;
+ }
+
+ @Override
+ public HelpCtx getHelp() {
+ return bottomPanel != null ?
+ bottomPanel.getHelp() :
+ null;
+ }
+
+ @Override
+ public boolean isValid() {
+ if (gui == null) {
+ setErrorMessage( null );
+ return false;
+ }
+ if (type == Type.PACKAGE) {
+ if (gui.getTargetName() == null) {
+ setErrorMessage("INFO_JavaTargetChooser_ProvidePackageName");
+ return false;
+ }
+ if ( !isValidPackageName( gui.getTargetName() ) ) {
+ setErrorMessage( "ERR_JavaTargetChooser_InvalidPackage" );
+ return false;
+ }
+ if (!isValidPackage(gui.getRootFolder(), gui.getTargetName())) {
+ setErrorMessage("ERR_JavaTargetChooser_InvalidFolder");
+ return false;
+ }
+ } else if (type == Type.PKG_INFO) {
+ //Change in firing order caused that isValid is called before readSettings completed => no targetName available
+ if (gui.getTargetName() == null) {
+ setErrorMessage("INFO_JavaTargetChooser_ProvideClassName");
+ return false;
+ }
+ assert "package-info".equals( gui.getTargetName() ); //NOI18N
+ if ( !isValidPackageName( gui.getPackageName() ) ) {
+ setErrorMessage( "ERR_JavaTargetChooser_InvalidPackage" );
+ return false;
+ }
+ if (!isValidPackage(gui.getRootFolder(), gui.getPackageName())) {
+ setErrorMessage("ERR_JavaTargetChooser_InvalidFolder");
+ return false;
+ }
+ } else {
+ if (gui.getTargetName() == null) {
+ setErrorMessage("INFO_JavaTargetChooser_ProvideClassName");
+ return false;
+ }
+ else if ( !isValidTypeIdentifier( gui.getTargetName() ) ) {
+ setErrorMessage( "ERR_JavaTargetChooser_InvalidClass" );
+ return false;
+ }
+ else if ( !isValidPackageName( gui.getPackageName() ) ) {
+ setErrorMessage( "ERR_JavaTargetChooser_InvalidPackage" );
+ return false;
+ }
+ if (!isValidPackage(gui.getRootFolder(), gui.getPackageName())) {
+ setErrorMessage("ERR_JavaTargetChooser_InvalidFolder");
+ return false;
+ }
+ }
+
+ // check if the file name can be created
+ FileObject template = Templates.getTemplate( wizard );
+
+ boolean returnValue=true;
+ FileObject rootFolder = gui.getRootFolder();
+ SpecificationVersion specVersion = null;
+ if (type != Type.PACKAGE) {
+ String sl = SourceLevelQuery.getSourceLevel(rootFolder);
+ specVersion = sl != null? new SpecificationVersion(sl): null;
+ }
+ String errorMessage = canUseFileName (rootFolder, gui.getPackageFileName(), gui.getTargetName(), template.getExt ());
+ if (gui != null) {
+ wizard.getNotificationLineSupport ().setErrorMessage (errorMessage);
+ }
+ if (errorMessage!=null) returnValue=false;
+
+ if (type != Type.PACKAGE && returnValue && gui.getPackageName().length() == 0 && specVersion != null && JDK_14.compareTo(specVersion) <= 0) {
+ if(isValidPackageRequired){
+ setInfoMessage( "ERR_JavaTargetChooser_CantUseDefaultPackage" );
+ return false;
+ }
+ //Only warning, display it only if everything else is OK.
+ setErrorMessage( "ERR_JavaTargetChooser_DefaultPackage" );
+ }
+ String categories = (String) template.getAttribute("templateCategory"); // NOI18N
+ if (categories != null && Arrays.asList(categories.split(",")).contains("jdk5")) {
+ //Only warning, display it only if everything else id OK.
+ if (specVersion != null && specVersion.compareTo(JDK_14) <= 0) {
+ wizard.getNotificationLineSupport().setErrorMessage("Error");
+ }
+ }
+
+ // this enables to display error messages from the bottom panel
+ // Nevertheless, the previous error messages have bigger priorities
+ if (returnValue && bottomPanel != null) {
+ if (!bottomPanel.isValid())
+ return false;
+ }
+
+ return returnValue;
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener l) {
+ listeners.add(l);
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener l) {
+ listeners.remove(l);
+ }
+
+ private void fireChange() {
+ ChangeEvent e = new ChangeEvent(this);
+ Iterator it = listeners.iterator();
+ while (it.hasNext()) {
+ ((ChangeListener)it.next()).stateChanged(e);
+ }
+ }
+
+ @Override
+ public void readSettings(WizardDescriptor wizard) {
+ this.wizard = wizard;
+ if ( gui != null ) {
+ // Try to preselect a folder
+ FileObject preselectedFolder = Templates.getTargetFolder( wizard );
+ // Init values
+ gui.initValues( Templates.getTemplate( wizard ), preselectedFolder );
+ }
+
+ if ( bottomPanel != null ) {
+ bottomPanel.readSettings(wizard);
+ }
+
+ // XXX hack, TemplateWizard in final setTemplateImpl() forces new wizard's title
+ // this name is used in NewFileWizard to modify the title
+ if (gui != null) {
+ Object substitute = gui.getClientProperty ("NewFileWizard_Title"); // NOI18N
+ if (substitute != null) {
+ wizard.putProperty ("NewFileWizard_Title", substitute); // NOI18N
+ }
+ }
+ }
+
+ @Override
+ public void storeSettings(WizardDescriptor wizard) {
+ Object value = wizard.getValue();
+ if (WizardDescriptor.PREVIOUS_OPTION.equals(value) || WizardDescriptor.CANCEL_OPTION.equals(value) ||
+ WizardDescriptor.CLOSED_OPTION.equals(value)) {
+ return;
+ }
+ if( isValid() ) {
+ if ( bottomPanel != null ) {
+ bottomPanel.storeSettings( wizard );
+ }
+ Templates.setTargetFolder(wizard, getTargetFolderFromGUI(wizard));
+ Templates.setTargetName(wizard, gui.getTargetName());
+ }
+ wizard.putProperty("NewFileWizard_Title", null); // NOI18N
+
+ if (WizardDescriptor.FINISH_OPTION.equals(value)) {
+ wizard.putProperty(FOLDER_TO_DELETE, null);
+ }
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ fireChange();
+ }
+
+ // Private methods ---------------------------------------------------------
+
+ private void setErrorMessage( String key ) {
+ if ( key == null ) {
+ wizard.getNotificationLineSupport().clearMessages();
+ } else {
+ wizard.getNotificationLineSupport().setErrorMessage(NbBundle.getMessage(TargetChooserPanelGUI.class, key));
+ }
+ }
+
+ private void setInfoMessage(String key) {
+ if (key == null) {
+ wizard.getNotificationLineSupport().clearMessages();
+ } else {
+ wizard.getNotificationLineSupport().setInformationMessage (NbBundle.getMessage(TargetChooserPanelGUI.class, key));
+ }
+ }
+
+ private FileObject getTargetFolderFromGUI (WizardDescriptor wd) {
+ assert gui != null;
+ FileObject rootFolder = gui.getRootFolder();
+ if (!rootFolder.isValid()) {
+ return null;
+ }
+ FileObject folder = null;
+ if (type != Type.PACKAGE) {
+ String packageFileName = gui.getPackageFileName();
+ folder = rootFolder.getFileObject( packageFileName );
+ if ( folder == null ) {
+ try {
+ folder = rootFolder;
+ StringTokenizer tk = new StringTokenizer (packageFileName,"/"); //NOI18N
+ String name = null;
+ while (tk.hasMoreTokens()) {
+ name = tk.nextToken();
+ FileObject fo = folder.getFileObject (name,""); //NOI18N
+ if (fo == null) {
+ break;
+ }
+ folder = fo;
+ }
+ folder = folder.createFolder(name);
+ FileObject toDelete = (FileObject) wd.getProperty(FOLDER_TO_DELETE);
+ if (toDelete == null) {
+ wd.putProperty(FOLDER_TO_DELETE,folder);
+ }
+ else if (!toDelete.equals(folder)) {
+ toDelete.delete();
+ wd.putProperty(FOLDER_TO_DELETE,folder);
+ }
+ while (tk.hasMoreTokens()) {
+ name = tk.nextToken();
+ folder = folder.createFolder(name);
+ }
+
+ }
+ catch( IOException e ) {
+ Exceptions.printStackTrace(e);
+ folder = null;
+ }
+ }
+ }
+ else {
+ folder = rootFolder;
+ }
+ return folder;
+ }
+
+ public String getPackageName(){
+ return gui.getPackageName();
+ }
+
+ // Nice copy of useful methods (Taken from JavaModule)
+
+ static boolean isValidPackageName(String str) {
+ if (str.length() > 0 && str.charAt(0) == '.') {
+ return false;
+ }
+ StringTokenizer tukac = new StringTokenizer(str, ".");
+ while (tukac.hasMoreTokens()) {
+ String token = tukac.nextToken();
+ if ("".equals(token))
+ return false;
+ if (!Utilities.isJavaIdentifier(token))
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean isValidPackage (FileObject root, final String path) {
+ //May be null when nothing selected in the GUI.
+ if (root == null) {
+ return false;
+ }
+ if (path == null) {
+ return false;
+ }
+ final StringTokenizer tk = new StringTokenizer(path,"."); //NOI18N
+ while (tk.hasMoreTokens()) {
+ root = root.getFileObject(tk.nextToken());
+ if (root == null) {
+ return true;
+ }
+ else if (root.isData()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static String[] getPackageAndSimpleName(final String name) {
+ final int lastDot = name.lastIndexOf('.'); //NOI18N
+ if (lastDot > 0) {
+ return new String[] {
+ name.substring(0, lastDot),
+ lastDot == name.length() - 1 ?
+ "" : //NOI18N
+ name.substring(lastDot+1)
+ };
+ } else {
+ return new String[] {
+ "", //NOI18N
+ name
+ };
+ }
+ }
+
+ private static boolean isValidTypeIdentifier(String ident) {
+ return ident != null && !"".equals(ident) && Utilities.isJavaIdentifier( ident ); //NOI18N
+ }
+
+ // helper methods copied from project/ui/ProjectUtilities
+ /** Checks if the given file name can be created in the target folder.
+ *
+ * @param targetFolder target folder (e.g. source group)
+ * @param folderName name of the folder relative to target folder
+ * @param newObjectName name of created file
+ * @param extension extension of created file
+ * @return localized error message or null if all right
+ */
+ public static String canUseFileName (FileObject targetFolder, String folderName, String newObjectName, String extension) {
+ String newObjectNameToDisplay = newObjectName;
+ if (newObjectName != null) {
+ newObjectName = newObjectName.replace ('.', '/'); // NOI18N
+ }
+ if (extension != null && extension.length () > 0) {
+ StringBuilder sb = new StringBuilder ();
+ sb.append (newObjectName);
+ sb.append ('.'); // NOI18N
+ sb.append (extension);
+ newObjectName = sb.toString ();
+ }
+
+ if (extension != null && extension.length () > 0) {
+ StringBuilder sb = new StringBuilder ();
+ sb.append (newObjectNameToDisplay);
+ sb.append ('.'); // NOI18N
+ sb.append (extension);
+ newObjectNameToDisplay = sb.toString ();
+ }
+
+ String relFileName = folderName + "/" + newObjectName; // NOI18N
+
+ // test whether the selected folder on selected filesystem already exists
+ if (targetFolder == null || !targetFolder.isValid()) {
+ return NbBundle.getMessage (TargetChooserPanel.class, "MSG_fs_or_folder_does_not_exist"); // NOI18N
+ }
+
+ // target package should be writable
+ File targetPackage = folderName != null ? new File (FileUtil.toFile (targetFolder), folderName) : FileUtil.toFile (targetFolder);
+ if (targetPackage != null) {
+ if (targetPackage.exists () && ! targetPackage.canWrite ()) {
+ return NbBundle.getMessage (TargetChooserPanel.class, "MSG_fs_is_readonly"); // NOI18N
+ }
+ } else if (! targetFolder.canWrite ()) {
+ return NbBundle.getMessage (TargetChooserPanel.class, "MSG_fs_is_readonly"); // NOI18N
+ }
+
+ if (existFileName(targetFolder, relFileName)) {
+ return NbBundle.getMessage (TargetChooserPanel.class, "MSG_file_already_exist", newObjectNameToDisplay); // NOI18N
+ }
+
+ // all ok
+ return null;
+ }
+
+ private static boolean existFileName(FileObject targetFolder, String relFileName) {
+ File fileForTargetFolder = FileUtil.toFile(targetFolder);
+ return fileForTargetFolder.exists() ?
+ new File (fileForTargetFolder, relFileName).exists() :
+ targetFolder.getFileObject (relFileName) != null;
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/TargetChooserPanelGUI.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/TargetChooserPanelGUI.java
new file mode 100644
index 0000000..c4453b6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/TargetChooserPanelGUI.java
@@ -0,0 +1,665 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates.packagechooser;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.Icon;
+import javax.swing.JList;
+import javax.swing.ListModel;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentListener;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.spi.java.project.support.ui.PackageView;
+import org.openide.awt.Mnemonics;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class TargetChooserPanelGUI extends javax.swing.JPanel implements ActionListener, DocumentListener {
+private static final String DEFAULT_NEW_PACKAGE_NAME =
+ NbBundle.getMessage( TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_DefaultNewPackageName" ); // NOI18N
+ private static final String NEW_CLASS_PREFIX =
+ NbBundle.getMessage( TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_NewJavaClassPrefix" ); // NOI18N
+
+ /** preferred dimension of the panel */
+ private static final Dimension PREF_DIM = new Dimension(500, 340);
+
+ private final Project project;
+ private final SourceGroup groups[];
+ private final List<ChangeListener> listeners = new ArrayList<ChangeListener>();
+ private final Type type;
+ private final ThreadLocal<Boolean> ignoreChange;
+
+ private String expectedExtension;
+ private boolean ignoreRootCombo;
+ private boolean wasPreviouslyFQN = false;
+ private String originalPackageName;
+ private final String fileType;
+
+ /** Creates new form SimpleTargetChooserGUI */
+ public TargetChooserPanelGUI(Project p, SourceGroup[] groups, Component bottomPanel, Type type, String fileType) {
+ this.type = type;
+ this.project = p;
+ this.groups = groups;
+ this.ignoreChange = new ThreadLocal<Boolean>();
+ this.fileType = fileType;
+ for (SourceGroup sourceGroup : groups)
+ if (sourceGroup == null)
+ throw new NullPointerException ();
+
+ initComponents();
+
+ if (type == Type.PACKAGE) {
+ packageComboBox.setVisible( false );
+ packageLabel.setVisible( false );
+ Mnemonics.setLocalizedText (fileLabel, NbBundle.getMessage (TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_CreatedFolder_Label")); // NOI18N
+ Mnemonics.setLocalizedText (documentNameLabel, NbBundle.getMessage (TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_PackageName_Label")); // NOI18N
+ documentNameTextField.getDocument().addDocumentListener( this );
+ } else if (type == Type.PKG_INFO) {
+ documentNameTextField.setEditable (false);
+ }
+ else {
+ packageComboBox.getEditor().addActionListener( this );
+ documentNameTextField.getDocument().addDocumentListener( this );
+ }
+
+
+ if ( bottomPanel != null ) {
+ bottomPanelContainer.add( bottomPanel, java.awt.BorderLayout.CENTER );
+ }
+
+ //initValues( project, null, null );
+
+
+ // Not very nice
+ Component packageEditor = packageComboBox.getEditor().getEditorComponent();
+ if ( packageEditor instanceof javax.swing.JTextField ) {
+ ((javax.swing.JTextField)packageEditor).getDocument().addDocumentListener( this );
+ }
+ else {
+ packageComboBox.addActionListener( this );
+ }
+
+ rootComboBox.setRenderer(new GroupListCellRenderer());
+ packageComboBox.setRenderer(PackageView.listRenderer());
+ rootComboBox.addActionListener( this );
+
+ setPreferredSize( PREF_DIM );
+ setName( NbBundle.getBundle (TargetChooserPanelGUI.class).getString ("LBL_JavaTargetChooserPanelGUI_Name") ); // NOI18N
+ }
+
+ @Override
+ public void addNotify () {
+ Dimension panel2Size = this.jPanel2.getPreferredSize();
+ Dimension bottomPanelSize = this.bottomPanelContainer.getPreferredSize ();
+ Dimension splitterSize = this.targetSeparator.getPreferredSize();
+ int vmax = panel2Size.height + bottomPanelSize.height + splitterSize.height + 12; //Insets=12
+ //Update only height, keep the wizard width
+ if (vmax > PREF_DIM.height) {
+ this.setPreferredSize (new Dimension (PREF_DIM.width,vmax));
+ }
+ super.addNotify();
+ }
+
+ public void initValues( FileObject template, FileObject preselectedFolder ) {
+ assert project != null : "Project must be specified."; // NOI18N
+ // Show name of the project
+ projectTextField.setText( ProjectUtils.getInformation(project).getDisplayName() );
+ assert template != null;
+
+ String displayName;
+ try {
+ DataObject templateDo = DataObject.find (template);
+ displayName = templateDo.getNodeDelegate ().getDisplayName ();
+ } catch (DataObjectNotFoundException ex) {
+ displayName = template.getName ();
+ }
+
+ putClientProperty ("NewFileWizard_Title", displayName);// NOI18N
+ // Setup comboboxes
+ rootComboBox.setModel(new DefaultComboBoxModel(groups));
+ SourceGroup preselectedGroup = getPreselectedGroup( preselectedFolder );
+ ignoreRootCombo = true;
+ rootComboBox.setSelectedItem( preselectedGroup );
+ ignoreRootCombo = false;
+ Object preselectedPackage = getPreselectedPackage(preselectedGroup, preselectedFolder, packageComboBox.getModel());
+ if (type == Type.PACKAGE) {
+ final String baseName = DEFAULT_NEW_PACKAGE_NAME;
+ String activeName = baseName;
+ if (preselectedFolder != null) {
+ int index = 0;
+ while (true) {
+ FileObject _tmp = preselectedFolder.getFileObject(activeName, null);
+ if (_tmp == null) {
+ break;
+ }
+ activeName = baseName + ++index;
+ }
+ }
+ String docName = preselectedPackage == null || preselectedPackage.toString().length() == 0 ?
+ activeName :
+ preselectedPackage.toString() + "." + activeName;
+
+ documentNameTextField.setText( docName );
+ int docNameLen = docName.length();
+ int defPackageNameLen = activeName.length();
+
+ documentNameTextField.setSelectionEnd( docNameLen - 1 );
+ documentNameTextField.setSelectionStart( docNameLen - defPackageNameLen );
+ } else {
+ if (preselectedPackage != null) {
+ // packageComboBox.setSelectedItem( preselectedPackage );
+ packageComboBox.getEditor().setItem( preselectedPackage );
+ PackageChooser.pack = (String) preselectedPackage;
+ }
+ if (template != null) {
+ if ( documentNameTextField.getText().trim().length() == 0 ) { // To preserve the class name on back in the wiazard
+ if (type == Type.PKG_INFO) {
+ documentNameTextField.setText (template.getName ());
+ }
+ else {
+ //Ordinary file
+ final String baseName = NEW_CLASS_PREFIX + template.getName ();
+ String activeName = baseName;
+ if (preselectedFolder != null) {
+ int index = 0;
+ while (true) {
+ FileObject _tmp = preselectedFolder.getFileObject(activeName, template.getExt()); //NOI18N
+ if (_tmp == null) {
+ break;
+ }
+ activeName = baseName + ++index;
+ }
+ }
+ documentNameTextField.setText (activeName);
+ documentNameTextField.selectAll ();
+ }
+ }
+ }
+ updatePackages();
+ }
+ // Determine the extension
+ String ext = template == null ? "" : template.getExt(); // NOI18N
+ expectedExtension = ext.length() == 0 ? "" : "." + ext; // NOI18N
+
+ updateText();
+
+ }
+
+ public FileObject getRootFolder() {
+ final Object selectedItem = rootComboBox.getSelectedItem();
+ return (selectedItem instanceof SourceGroup) ? ((SourceGroup)selectedItem).getRootFolder() : null;
+ }
+
+ public String getPackageFileName() {
+
+ if (type == Type.PACKAGE) {
+ return ""; // NOI18N
+ }
+
+ String packageName = packageComboBox.getEditor().getItem().toString();
+ return packageName.replace( '.', '/' ); // NOI18N
+ }
+
+ /**
+ * Name of selected package, or "" for default package.
+ */
+ String getPackageName() {
+ if (type == Type.PACKAGE) {
+ return ""; // NOI18N
+ }
+ return packageComboBox.getEditor().getItem().toString();
+ }
+
+ public String getTargetName() {
+ String text;
+ final String rawName = documentNameTextField.getText().trim();
+ if (type == Type.PACKAGE) {
+ text = rawName;
+ } else {
+ final String[] pkgNamePair = TargetChooserPanel.getPackageAndSimpleName(rawName);
+ if (pkgNamePair[0].length() == 0) {
+ text = rawName;
+ } else {
+ text = pkgNamePair[1];
+ }
+ }
+ if ( text.length() == 0 ) {
+ return null;
+ } else {
+ return text;
+ }
+ }
+
+ public void addChangeListener(ChangeListener l) {
+ listeners.add(l);
+ }
+
+ public void removeChangeListener(ChangeListener l) {
+ listeners.remove(l);
+ }
+
+ private void fireChange() {
+ if (packageComboBox.getSelectedItem() != null) {
+ PackageChooser.pack = packageComboBox.getSelectedItem().toString();
+ }
+ ChangeEvent e = new ChangeEvent(this);
+ for (ChangeListener l : listeners) {
+ l.stateChanged(e);
+ }
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">
+ private void initComponents() {
+ java.awt.GridBagConstraints gridBagConstraints;
+
+ targetSeparator = new javax.swing.JSeparator();
+ bottomPanelContainer = new javax.swing.JPanel();
+ jPanel2 = new javax.swing.JPanel();
+ jPanel1 = new javax.swing.JPanel();
+ documentNameLabel = new javax.swing.JLabel();
+ documentNameTextField = new javax.swing.JTextField();
+ jLabel5 = new javax.swing.JLabel();
+ projectTextField = new javax.swing.JTextField();
+ jLabel1 = new javax.swing.JLabel();
+ rootComboBox = new javax.swing.JComboBox();
+ packageLabel = new javax.swing.JLabel();
+ packageComboBox = new javax.swing.JComboBox();
+ fileLabel = new javax.swing.JLabel();
+ fileTextField = new javax.swing.JTextField();
+
+ setLayout(new java.awt.GridBagLayout());
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0);
+ add(targetSeparator, gridBagConstraints);
+
+ bottomPanelContainer.setLayout(new java.awt.BorderLayout());
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.weighty = 1.0;
+ add(bottomPanelContainer, gridBagConstraints);
+
+ jPanel2.setLayout(new java.awt.GridBagLayout());
+
+ jPanel1.setLayout(new java.awt.GridBagLayout());
+
+ documentNameLabel.setLabelFor(documentNameTextField);
+
+ org.openide.awt.Mnemonics.
+ setLocalizedText(documentNameLabel, fileType + ":"); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ jPanel1.add(documentNameLabel, gridBagConstraints);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
+ jPanel1.add(documentNameTextField, gridBagConstraints);
+ java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jetbrains/kotlin/file/templates/packagechooser/Bundle"); // NOI18N
+ documentNameTextField.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_documentNameTextField")); // NOI18N
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 24, 0);
+ jPanel2.add(jPanel1, gridBagConstraints);
+
+ jLabel5.setLabelFor(projectTextField);
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_jLabel5")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
+ jPanel2.add(jLabel5, gridBagConstraints);
+
+ projectTextField.setEditable(false);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
+ jPanel2.add(projectTextField, gridBagConstraints);
+ projectTextField.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_projectTextField")); // NOI18N
+
+ jLabel1.setLabelFor(rootComboBox);
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_jLabel1")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
+ jPanel2.add(jLabel1, gridBagConstraints);
+
+ rootComboBox.setMinimumSize(new java.awt.Dimension(154, 27));
+ rootComboBox.setPreferredSize(new java.awt.Dimension(154, 27));
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
+ jPanel2.add(rootComboBox, gridBagConstraints);
+ rootComboBox.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_rootComboBox")); // NOI18N
+
+ packageLabel.setLabelFor(packageComboBox);
+ org.openide.awt.Mnemonics.setLocalizedText(packageLabel, org.openide.util.NbBundle.getMessage(TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_jLabel2")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 6, 0);
+ jPanel2.add(packageLabel, gridBagConstraints);
+
+ packageComboBox.setEditable(true);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(0, 6, 6, 0);
+ jPanel2.add(packageComboBox, gridBagConstraints);
+ packageComboBox.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_packageComboBox")); // NOI18N
+
+ fileLabel.setLabelFor(fileTextField);
+ org.openide.awt.Mnemonics.setLocalizedText(fileLabel, org.openide.util.NbBundle.getMessage(TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_CreatedFile_Label")); // NOI18N
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(6, 0, 12, 0);
+ jPanel2.add(fileLabel, gridBagConstraints);
+
+ fileTextField.setEditable(false);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.insets = new java.awt.Insets(6, 6, 12, 0);
+ jPanel2.add(fileTextField, gridBagConstraints);
+ fileTextField.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_fileTextField")); // NOI18N
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1.0;
+ add(jPanel2, gridBagConstraints);
+
+ getAccessibleContext().setAccessibleDescription(bundle.getString("AD_JavaTargetChooserPanelGUI")); // NOI18N
+ }// </editor-fold>
+
+
+
+ // Variables declaration - do not modify
+ private javax.swing.JPanel bottomPanelContainer;
+ private javax.swing.JLabel documentNameLabel;
+ private javax.swing.JTextField documentNameTextField;
+ private javax.swing.JLabel fileLabel;
+ private javax.swing.JTextField fileTextField;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel5;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JPanel jPanel2;
+ private javax.swing.JComboBox packageComboBox;
+ private javax.swing.JLabel packageLabel;
+ private javax.swing.JTextField projectTextField;
+ private javax.swing.JComboBox rootComboBox;
+ private javax.swing.JSeparator targetSeparator;
+ // End of variables declaration
+
+ // ActionListener implementation -------------------------------------------
+
+ @Override
+ public void actionPerformed(java.awt.event.ActionEvent e) {
+ if (ignoreChange.get() == Boolean.TRUE) {
+ return;
+ }
+ if ( rootComboBox == e.getSource() ) {
+ if (!ignoreRootCombo && type != Type.PACKAGE) {
+ updatePackages();
+ }
+ updateText();
+ fireChange();
+ }
+ else if ( packageComboBox == e.getSource() ) {
+ updateText();
+ fireChange();
+ }
+ else if ( packageComboBox.getEditor() == e.getSource() ) {
+ updateText();
+ fireChange();
+ }
+ }
+
+ // DocumentListener implementation -----------------------------------------
+
+ @Override
+ public void changedUpdate(javax.swing.event.DocumentEvent e) {
+ updateText();
+ fireChange();
+ }
+
+ @Override
+ public void insertUpdate(javax.swing.event.DocumentEvent e) {
+ changedUpdate( e );
+ }
+
+ @Override
+ public void removeUpdate(javax.swing.event.DocumentEvent e) {
+ changedUpdate( e );
+ }
+
+ // Private methods ---------------------------------------------------------
+
+ private RequestProcessor.Task updatePackagesTask = null;
+
+ private static final ComboBoxModel WAIT_MODEL = new DefaultComboBoxModel(
+ new String[] {
+ NbBundle.getMessage(TargetChooserPanelGUI.class, "LBL_JavaTargetChooserPanelGUI_PackageName_PleaseWait") // NOI18N
+ }
+ );
+
+ private void updatePackages() {
+ final Object item = rootComboBox.getSelectedItem();
+ if (! (item instanceof SourceGroup)) {
+ return;
+ }
+ WAIT_MODEL.setSelectedItem( packageComboBox.getEditor().getItem() );
+ packageComboBox.setModel( WAIT_MODEL );
+
+ if ( updatePackagesTask != null ) {
+ updatePackagesTask.cancel();
+ }
+
+ updatePackagesTask = new RequestProcessor( "ComboUpdatePackages" ).post(new Runnable() {
+ @Override
+ public void run() {
+ final ComboBoxModel model = PackageView.createListView((SourceGroup)item);
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run () {
+ model.setSelectedItem(packageComboBox.getEditor().getItem());
+ packageComboBox.setModel( model );
+ }
+ });
+ }
+ });
+ }
+
+ private void updateText() {
+ final Object selectedItem = rootComboBox.getSelectedItem();
+ String createdFileName;
+ if (selectedItem instanceof SourceGroup) {
+ SourceGroup g = (SourceGroup) selectedItem;
+ FileObject rootFolder = g.getRootFolder();
+ String packageName = getPackageFileName();
+ String documentName = documentNameTextField.getText().trim();
+ if (Type.FILE.equals(type)) {
+ final String[] pkgNamePair = TargetChooserPanel.getPackageAndSimpleName(documentName);
+ final boolean fqn = !pkgNamePair[0].isEmpty();
+ if (fqn) {
+ if (!wasPreviouslyFQN) {
+ //backup the original package name
+ originalPackageName = getPackageName();
+ }
+ //set the textfield from the parsed FQN text
+ packageName = pkgNamePair[0];
+ documentName = pkgNamePair[1];
+ setPackageIgnoreEvents(packageName);
+ packageName = packageName.replace('.', '/'); //NOI18N
+ wasPreviouslyFQN = true;
+ } else {
+ if (wasPreviouslyFQN) {
+ //reset the package name, if the user reverts his previously entered FQN
+ setPackageIgnoreEvents(originalPackageName);
+ wasPreviouslyFQN = false;
+ }
+ }
+ packageComboBox.setEnabled(!fqn);
+ }
+ if (type == Type.PACKAGE) {
+ documentName = documentName.replace( '.', '/' ); // NOI18N
+ }
+ else if ( documentName.length() > 0 ) {
+ documentName = documentName + expectedExtension;
+ }
+ createdFileName = FileUtil.getFileDisplayName( rootFolder ) +
+ ( packageName.startsWith("/") || packageName.startsWith( File.separator ) ? "" : "/" ) + // NOI18N
+ packageName +
+ ( packageName.endsWith("/") || packageName.endsWith( File.separator ) || packageName.length() == 0 ? "" : "/" ) + // NOI18N
+ documentName;
+ } else {
+ //May be null iff nothing selected
+ createdFileName = ""; //NOI18N
+ }
+ fileTextField.setText( createdFileName.replace( '/', File.separatorChar ) ); // NOI18N
+ }
+
+ private SourceGroup getPreselectedGroup(FileObject folder) {
+ for(int i = 0; folder != null && i < groups.length; i++) {
+ FileObject root = groups[i].getRootFolder();
+ if (root.equals(folder) || FileUtil.isParentOf(root, folder)) {
+ return groups[i];
+ }
+ }
+ return groups[0];
+ }
+
+ /**
+ * Get a package combo model item for the package the user selected before opening the wizard.
+ * May return null if it cannot find it; or a String instance if there is a well-defined
+ * package but it is not listed among the packages shown in the list model.
+ */
+ private Object getPreselectedPackage(SourceGroup group, FileObject folder, ListModel model) {
+ if ( folder == null ) {
+ return null;
+ }
+ FileObject root = group.getRootFolder();
+
+ String relPath = FileUtil.getRelativePath( root, folder );
+
+ if ( relPath == null ) {
+ // Group Root folder is no a parent of the preselected folder
+ // No package should be selected
+ return null;
+ }
+ else {
+ // Find the right item.
+ String name = relPath.replace('/', '.');
+ /*
+ int max = model.getSize();
+ for (int i = 0; i < max; i++) {
+ Object item = model.getElementAt(i);
+ if (item.toString().equals(name)) {
+ return item;
+ }
+ }
+ */
+ // Didn't find it.
+ // #49954: should nonetheless show something in the combo box.
+ return name;
+ }
+ }
+
+ private void setPackageIgnoreEvents(final String text) {
+ ignoreChange.set(true);
+ try {
+ packageComboBox.setSelectedItem(text);
+ } finally {
+ ignoreChange.remove();
+ }
+ }
+
+ // Private innerclasses ----------------------------------------------------
+
+ /**
+ * Displays a {@link SourceGroup} in {@link #rootComboBox}.
+ */
+ private static final class GroupListCellRenderer extends DefaultListCellRenderer/*<SourceGroup>*/ {
+
+ public GroupListCellRenderer() {}
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ String name;
+ Icon icon;
+ if (value == null) {
+ name = ""; //NOI18N
+ icon = null;
+ }
+ else {
+ assert value instanceof SourceGroup;
+ SourceGroup g = (SourceGroup) value;
+ name = g.getDisplayName();
+ icon = g.getIcon(false);
+ }
+ super.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
+ setIcon(icon);
+ return this;
+ }
+
+ }
+
+
+}
+
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/Type.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/Type.java
new file mode 100644
index 0000000..813744d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/file/templates/packagechooser/Type.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.file.templates.packagechooser;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public enum Type {FILE, PACKAGE, PKG_INFO}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/JavaStubGenerator.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/JavaStubGenerator.kt
new file mode 100644
index 0000000..085988b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/JavaStubGenerator.kt
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem
+
+import kotlin.Pair
+import org.jetbrains.org.objectweb.asm.ClassReader
+import org.jetbrains.org.objectweb.asm.Opcodes
+import org.jetbrains.org.objectweb.asm.tree.ClassNode
+import org.jetbrains.org.objectweb.asm.tree.MethodNode
+import org.jetbrains.org.objectweb.asm.tree.FieldNode
+import org.jetbrains.org.objectweb.asm.signature.SignatureReader
+import org.jetbrains.org.objectweb.asm.util.TraceSignatureVisitor
+
+object JavaStubGenerator {
+
+ fun gen(byteCodeList: List<ByteArray>): List<Pair<ClassNode, String>> {
+ val classNodes = byteCodeList.mapNotNull { it.getClassNode() }.distinctBy { it.name }
+ val innerClasses = hashMapOf<ClassNode, List<ClassNode>>()
+ val classes = classNodes.filter { !it.name.contains("$") }
+
+ classNodes.forEach { classNode ->
+ val innerClassesList = classNode.innerClasses
+ .mapNotNull { inner ->
+ classNodes.find { it.name == inner.name && inner.name.length > classNode.name.length }
+ }
+ innerClasses.put(classNode, innerClassesList)
+ }
+
+ return classes.map { generate(it, innerClasses) }
+ }
+
+ private fun generate(classNode: ClassNode,
+ innerClassesMap: Map<ClassNode, List<ClassNode>>): Pair<ClassNode, String> =
+ with (StringBuilder()) {
+ if (!classNode.name.contains("$")) append(classNode.packageString)
+ append(classNode.classDeclaration())
+ append(classNode.fields())
+ append(classNode.methods())
+ for (node in innerClassesMap[classNode]!!) {
+ append(generate(node, innerClassesMap).second).append("\n")
+ }
+
+ append("}")
+
+ return classNode to this.toString()
+ }
+
+ private fun ByteArray.getClassNode(): ClassNode? {
+ val classNode = ClassNode()
+ try {
+ ClassReader(this).accept(classNode, 0)
+ } catch (ex: Exception) {
+ return null
+ }
+
+ return classNode
+ }
+
+ private val ClassNode.packageString: String
+ get() = "package ${name.substringBeforeLast("/").replace("/", ".")};\n"
+
+ private val ClassNode.className: String
+ get() = if (!name.contains("$")) name.substringAfterLast("/") else name.substringAfterLast("$")
+
+ private fun ClassNode.classDeclaration(): String {
+ val declaration = StringBuilder()
+
+ val classType = getClassType(access)
+
+ declaration.append(getAccess(access)).append(" ")
+ declaration.append(getFinal(access)).append(" ")
+ declaration.append(getStatic(access)).append(" ")
+ if (classType != "interface") declaration.append(getAbstract(access)).append(" ")
+
+
+ val superTypes = if (signature != null) {
+ val signatureReader = SignatureReader(signature)
+ val traceSigVisitor = TraceSignatureVisitor(access)
+ signatureReader.accept(traceSigVisitor)
+
+ traceSigVisitor.declaration.replace("$", ".")
+ } else {
+ val superTypes = StringBuilder()
+ if (classType == "class") {
+ superTypes.append("extends ").append(superName.replace("/", ".").replace("$", "."))
+ superTypes.append(" ")
+ }
+
+ if (interfaces != null && interfaces.isNotEmpty()) {
+ when (classType) {
+ "interface" -> superTypes.append(" extends ")
+ "class" -> superTypes.append(" implements ")
+ }
+ }
+
+ superTypes.append(
+ interfaces.joinToString(", ", "", "", -1, "...",
+ { it.replace("/", ".").replace("$", ".") }
+ )
+ )
+
+ superTypes.toString()
+ }
+
+ declaration.append(classType).append(" ")
+ declaration.append(className).append(" ")
+ declaration.append(superTypes)
+
+ declaration.append("{\n")
+
+ return declaration.toString()
+ }
+
+ private fun ClassNode.fields(): String {
+ val fieldsStub = StringBuilder()
+
+ if (getClassType(access) == "enum") {
+ fieldsStub.append(
+ fields.joinToString(", ", "", "", -1, "...", { it.name })
+ ).append(";")
+ } else fields.forEach {
+ fieldsStub.append(it.getString())
+ }
+ return fieldsStub.toString()
+ }
+
+ private fun FieldNode.getString(): String {
+ val sig = if (signature != null) signature else desc
+
+ val signatureReader = SignatureReader(sig)
+ val traceSigVisitor = TraceSignatureVisitor(access)
+ signatureReader.accept(traceSigVisitor)
+
+ val type = traceSigVisitor.declaration.substringAfterLast(" ")
+
+ with (StringBuilder()) {
+ append(getAccess(access)).append(" ")
+ append(getFinal(access)).append(" ")
+ append(getStatic(access)).append(" ")
+ append(type.replace("$", ".")).append(" ")
+ append(name).append(";\n")
+
+ return toString()
+ }
+ }
+
+ private fun ClassNode.methods(): String {
+ val methodsStub = StringBuilder()
+
+ for (it in methods) {
+ methodsStub.append(it.getString(className))
+ }
+
+ return methodsStub.toString()
+ }
+
+ private fun MethodNode.getString(className: String): String {
+ val method = StringBuilder()
+
+ val sig = if (signature != null) signature else desc
+
+ method.append(getAccess(access)).append(" ")
+ method.append(getFinal(access)).append(" ")
+ method.append(getStatic(access)).append(" ")
+ method.append(getAbstract(access)).append(" ")
+
+ val methodName = if (name == "<init>") className else name
+
+ val traceSigVisitor = TraceSignatureVisitor(access)
+ SignatureReader(sig).accept(traceSigVisitor)
+
+ val returnType = if (name == "<init>") "" else traceSigVisitor.returnType
+
+ method.append(returnType.replace("$", ".")).append(" ").append(methodName)
+ .append(getMethodArguments(traceSigVisitor.declaration.replace("$", "."))).append("{}\n")
+
+ return method.toString()
+ }
+
+ private fun getMethodArguments(declaration: String): String {
+ val argumentsTypes = declaration.replace("(", "").replace(")", "").split(",")
+
+ return argumentsTypes.withIndex()
+ .joinToString(",", "(", ")", -1, "...", { if (it.value != "") "${it.value} a${it.index}" else "" })
+ }
+
+ private fun getClassType(access: Int) = when {
+ access.contains(Opcodes.ACC_INTERFACE) -> "interface"
+ access.contains(Opcodes.ACC_ENUM) -> "enum"
+ else -> "class"
+ }
+
+ private fun getAccess(access: Int) = when {
+ access.contains(Opcodes.ACC_PUBLIC) -> "public"
+ access.contains(Opcodes.ACC_PRIVATE) -> "private"
+ access.contains(Opcodes.ACC_PROTECTED) -> "protected"
+ else -> ""
+ }
+
+ private fun getFinal(access: Int) = if (access.contains(Opcodes.ACC_FINAL)) "final" else ""
+
+ private fun getStatic(access: Int) = if (access.contains(Opcodes.ACC_STATIC)) "static" else ""
+
+ private fun getAbstract(access: Int) = if (access.contains(Opcodes.ACC_ABSTRACT)) "abstract" else ""
+
+ private fun Int.contains(opcode: Int) = (this and opcode) != 0
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/KotlinLightClassManager.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/KotlinLightClassManager.kt
new file mode 100644
index 0000000..c785b5c
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/KotlinLightClassManager.kt
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem
+
+import com.intellij.openapi.components.ServiceManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import java.io.File
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.filesystem.lightclasses.LightClassFile
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.fileClasses.*
+import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
+import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.KtNamedFunction
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.KtSecondaryConstructor
+import org.jetbrains.kotlin.psi.KtVisitorVoid
+import org.openide.filesystems.FileObject
+import org.netbeans.api.project.Project as NBProject
+
+class KotlinLightClassManager(private val project: NBProject) {
+
+ companion object {
+ fun getInstance(project: NBProject): KotlinLightClassManager {
+ val ideaProject = KotlinEnvironment.getEnvironment(project).project
+ return ServiceManager.getService(ideaProject, KotlinLightClassManager::class.java)
+ }
+
+ fun getInternalName(classOrObject: KtClassOrObject): String? {
+ val fullFqName = classOrObject.fqName ?: return null
+ val topmostClassOrObject: KtClassOrObject = PsiTreeUtil.
+ getTopmostParentOfType(classOrObject, KtClassOrObject::class.java) ?: return makeInternalByToplevel(fullFqName)
+ val topLevelFqName = topmostClassOrObject.fqName ?: return null
+
+ val nestedPart = fullFqName.asString().substring(topLevelFqName.asString().length).replace(".", "$")
+ return "${makeInternalByToplevel(topLevelFqName)}$nestedPart"
+ }
+
+ private fun makeInternalByToplevel(fqName: FqName): String {
+ return fqName.asString().replace(".", "/")
+ }
+ }
+
+ private val sourceFiles = hashMapOf<File, Set<FileObject>>()
+
+ fun computeLightClassesSources() {
+ val newSourceFilesMap = hashMapOf<File, MutableSet<FileObject>>()
+ for (sourceFile in KotlinPsiManager.getFilesByProject(project)) {
+ val lightClassesPaths = getLightClassesPaths(sourceFile)
+ for (path in lightClassesPaths) {
+ val lightClassFile = LightClassFile(project, path)
+ var newSourceFiles = newSourceFilesMap[lightClassFile.asFile()]
+ if (newSourceFiles == null) {
+ newSourceFiles = hashSetOf<FileObject>()
+ newSourceFilesMap.put(lightClassFile.asFile(), newSourceFiles)
+ }
+
+ newSourceFiles.add(sourceFile)
+ }
+ }
+ sourceFiles.clear()
+ sourceFiles.putAll(newSourceFilesMap)
+ }
+
+ fun getLightClassesPaths(sourceFile: FileObject?): List<String> {
+ val lightClasses = arrayListOf<String>()
+ val ktFile = ProjectUtils.getKtFile(sourceFile)
+
+ findLightClasses(ktFile).forEach {
+ val internalName = getInternalName(it)
+ if (internalName != null) lightClasses.add(computePathByInternalName(internalName))
+ }
+
+ if (PackagePartClassUtils.fileHasTopLevelCallables(ktFile)) {
+ val newFacadeInternalName = NoResolveFileClassesProvider.getFileClassInternalName(ktFile)
+ lightClasses.add(computePathByInternalName(newFacadeInternalName))
+ }
+
+ return lightClasses
+ }
+
+ private fun findLightClasses(ktFile: KtFile): List<KtClassOrObject> {
+ val lightClasses = arrayListOf<KtClassOrObject>()
+
+ ktFile.acceptChildren(object : KtVisitorVoid() {
+ override fun visitClassOrObject(classOrObject: KtClassOrObject) {
+ lightClasses.add(classOrObject)
+ super.visitClassOrObject(classOrObject)
+ }
+
+ override fun visitNamedFunction(function: KtNamedFunction) {}
+
+ override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {}
+
+ override fun visitProperty(property: KtProperty) {}
+
+ override fun visitElement(element: PsiElement?) {
+ if (element != null) element.acceptChildren(this)
+ }
+ })
+
+ return lightClasses
+ }
+
+ private fun computePathByInternalName(internalName: String) = "${internalName}.class"
+
+ fun getSourceFiles(file: File): List<KtFile> {
+ if (sourceFiles.isEmpty()) computeLightClassesSources()
+
+ return getSourceKtFiles(file)
+ }
+
+ private fun getSourceKtFiles(file: File): List<KtFile> {
+ val sourceIOFiles = sourceFiles[file] ?: return emptyList()
+
+ return sourceIOFiles.mapNotNull { ProjectUtils.getKtFile(it) }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/KotlinVirtualSourceProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/KotlinVirtualSourceProvider.java
new file mode 100644
index 0000000..137a25f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/KotlinVirtualSourceProvider.java
@@ -0,0 +1,56 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.filesystem;
+
+import com.google.common.collect.Sets;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.java.preprocessorbridge.spi.VirtualSourceProvider;
+import org.openide.util.lookup.ServiceProvider;
+
+@ServiceProvider(service = VirtualSourceProvider.class)
+public class KotlinVirtualSourceProvider implements VirtualSourceProvider {
+
+ private static final List<Project> TRANSLATED_FULLY = new ArrayList<>();
+
+ public static boolean isFullyTranslated(Project project) {
+ return TRANSLATED_FULLY.contains(project);
+ }
+
+ public static void translated(Project project) {
+ TRANSLATED_FULLY.add(project);
+ }
+
+ @Override
+ public Set<String> getSupportedExtensions() {
+ return Sets.newHashSet("kt");
+ }
+
+ @Override
+ public boolean index() {
+ return false;
+ }
+
+ @Override
+ public void translate(Iterable<File> files, File sourceRoot, Result result) {
+ VirtualSourceUtilsKt.translate(files, result);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/BinaryClassWriter.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/BinaryClassWriter.kt
new file mode 100644
index 0000000..e625a5e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/BinaryClassWriter.kt
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem.lightclasses
+
+import org.jetbrains.org.objectweb.asm.ClassWriter
+
+class BinaryClassWriter : ClassWriter(ClassWriter.COMPUTE_FRAMES or ClassWriter.COMPUTE_MAXS) {
+
+ override fun getCommonSuperClass(type1: String, type2: String): String {
+ return try {
+ super.getCommonSuperClass(type1, type2)
+ } catch (t: Throwable) {
+ "java/lang/Object"
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/KotlinLightClassGeneration.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/KotlinLightClassGeneration.kt
new file mode 100644
index 0000000..9838551
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/KotlinLightClassGeneration.kt
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem.lightclasses
+
+import java.io.File
+import java.util.regex.Pattern
+import org.jetbrains.kotlin.filesystem.KotlinLightClassManager
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
+import org.jetbrains.kotlin.codegen.state.GenerationState
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.KtScript
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.netbeans.api.project.Project
+import org.openide.filesystems.FileObject
+
+object KotlinLightClassGeneration {
+
+ private fun buildLightClasses(analysisResult: AnalysisResult, project: Project,
+ ktFiles: List<KtFile>, requestedClassName: String): GenerationState? {
+ val generateDeclaredClassFilter = object : GenerationState.GenerateClassFilter() {
+ override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject) = true
+
+ override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject) = true
+
+ override fun shouldGeneratePackagePart(jetFile: KtFile) = true
+
+ override fun shouldGenerateScript(script: KtScript) = false
+
+ }
+
+ val state = GenerationState(
+ KotlinEnvironment.getEnvironment(project).project,
+ LightClassBuilderFactory(),
+ analysisResult.moduleDescriptor,
+ analysisResult.bindingContext,
+ ktFiles,
+ CompilerConfiguration.EMPTY,
+ generateDeclaredClassFilter)
+
+ ktFiles.forEach {
+ state.bindingContext[BindingContext.FILE_TO_PACKAGE_FRAGMENT, it] ?: return null
+ }
+
+ KotlinCodegenFacade.compileCorrectFiles(state, { _, _ -> Unit })
+
+ return state
+ }
+
+ fun getByteCode(file: FileObject, project: Project?,
+ analysisResult: AnalysisResult): List<ByteArray> {
+ if (project == null) return emptyList()
+
+ val code = arrayListOf<ByteArray>()
+
+ val manager = KotlinLightClassManager.getInstance(project)
+ manager.computeLightClassesSources()
+
+ manager.getLightClassesPaths(file).forEach {
+ val lightClass = File("${project.projectDirectory.path}${ProjectUtils.FILE_SEPARATOR}$it")
+ val ktFiles = manager.getSourceFiles(lightClass)
+ val className = it.substringAfterLast(Pattern.quote(ProjectUtils.FILE_SEPARATOR))
+ if (ktFiles.isNotEmpty()) {
+ try {
+ val state = buildLightClasses(analysisResult, project, ktFiles, className) ?: return emptyList()
+
+ state.factory.asList().forEach { outFile -> code.add(outFile.asByteArray()) }
+ } catch (ex: Exception) {
+ KotlinLogger.INSTANCE.logWarning("Couldn't create light class for ${file.path}")
+ return emptyList()
+ }
+ }
+ }
+
+ return code
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/LightClassBuilderFactory.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/LightClassBuilderFactory.kt
new file mode 100644
index 0000000..6c0e390
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/LightClassBuilderFactory.kt
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem.lightclasses
+
+import kotlin.Pair
+import org.jetbrains.kotlin.codegen.AbstractClassBuilder
+import org.jetbrains.kotlin.codegen.ClassBuilder
+import org.jetbrains.kotlin.codegen.ClassBuilderFactory
+import org.jetbrains.kotlin.codegen.ClassBuilderMode
+import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
+import org.jetbrains.org.objectweb.asm.ClassWriter
+import org.jetbrains.org.objectweb.asm.FieldVisitor
+import org.jetbrains.org.objectweb.asm.MethodVisitor
+import com.intellij.openapi.util.Key
+
+class LightClassBuilderFactory : ClassBuilderFactory {
+
+ override fun getClassBuilderMode(): ClassBuilderMode = ClassBuilderMode.LIGHT_CLASSES
+
+ override fun newClassBuilder(origin: JvmDeclarationOrigin): ClassBuilder {
+ return object : AbstractClassBuilder.Concrete(BinaryClassWriter()) {
+ override fun newMethod(origin: JvmDeclarationOrigin, access: Int, name: String,
+ desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor {
+ saveJvmSignature(origin, name, desc)
+ return super.newMethod(origin, access, name, desc, signature, exceptions)
+ }
+
+ override fun newField(origin: JvmDeclarationOrigin, access: Int, name: String,
+ desc: String, signature: String?, value: Any?): FieldVisitor {
+ saveJvmSignature(origin, name, desc)
+ return super.newField(origin, access, name, desc, signature, value)
+ }
+
+ private fun saveJvmSignature(origin: JvmDeclarationOrigin, name: String, desc: String) {
+ val element = origin.element ?: return
+
+ var userData = element.getUserData(JVM_SIGNATURE)
+ if (userData == null) {
+ userData = hashSetOf()
+ element.putUserData(JVM_SIGNATURE, userData)
+ }
+
+ userData.toMutableSet().add(Pair(desc, name))
+ }
+ }
+ }
+
+ override fun asText(builder: ClassBuilder) = throw UnsupportedOperationException("BINARIES generator asked for text")
+
+ override fun asBytes(builder: ClassBuilder): ByteArray = (builder.visitor as ClassWriter).toByteArray()
+
+ override fun close() {}
+
+ companion object {
+ val JVM_SIGNATURE: Key<Set<Pair<String, String>>> = Key.create("JVM_SIGNATURE")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/LightClassFile.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/LightClassFile.java
new file mode 100644
index 0000000..beff984
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/lightclasses/LightClassFile.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem.lightclasses;
+
+import java.io.File;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.jetbrains.annotations.NotNull;
+import org.netbeans.api.project.Project;
+
+public final class LightClassFile {
+ private final File file;
+
+ public LightClassFile(Project project, String path){
+ file = new File(project.getProjectDirectory().getPath() + ProjectUtils.FILE_SEPARATOR + path);
+ }
+ @NotNull
+ public File asFile(){
+ return file;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/virtualSourceUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/virtualSourceUtils.kt
new file mode 100644
index 0000000..839fa88
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/filesystem/virtualSourceUtils.kt
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.filesystem
+
+import java.io.File
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.resolve.NetBeansAnalyzerFacadeForJVM
+import org.jetbrains.kotlin.filesystem.lightclasses.KotlinLightClassGeneration
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.utils.hasMain
+import org.netbeans.api.project.Project
+import org.netbeans.modules.java.preprocessorbridge.spi.VirtualSourceProvider
+import org.openide.filesystems.FileObject
+import org.openide.filesystems.FileUtil
+
+fun translate(files: Iterable<File>, result: VirtualSourceProvider.Result) {
+ KotlinLogger.INSTANCE.logInfo("KotlinVirtualSourceProvider translate $files")
+
+ val filesToTranslate = if (files.firstOrNull().skipTranslating()) {
+ KotlinLogger.INSTANCE.logInfo("No java files. Translating only kt files with main functions")
+ files.mapNotNull { FileUtil.toFileObject(FileUtil.normalizeFile(it)) }
+ .filter { ProjectUtils.getKtFile(it).hasMain() }
+ } else files.mapNotNull { FileUtil.toFileObject(FileUtil.normalizeFile(it)) }
+
+ val project = filesToTranslate.firstOrNull()?.let { ProjectUtils.getKotlinProjectForFileObject(it) } ?: return
+
+ if (filesToTranslate.size == KotlinPsiManager.getFilesByProject(project, false).size) {
+ if (KotlinVirtualSourceProvider.isFullyTranslated(project)) return else KotlinVirtualSourceProvider.translated(project)
+ val startTime = System.nanoTime()
+ val analysisResult = NetBeansAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
+ project, KotlinEnvironment.getEnvironment(project).project,
+ ProjectUtils.getSourceFilesWithDependencies(project))
+ KotlinLogger.INSTANCE.logInfo("Kotlin analysis took ${(System.nanoTime() - startTime)}")
+ filesToTranslate.translate(result, analysisResult, project)
+ return
+ }
+
+ filesToTranslate.translate(result)
+}
+
+private fun List<FileObject>.translate(result: VirtualSourceProvider.Result,
+ analysisResult: AnalysisResultWithProvider? = null,
+ proj: Project? = null) = map { Pair(it, it.byteCode(analysisResult, proj)) }
+ .filter { it.second.isNotEmpty() }
+ .forEach {
+ val stubs = JavaStubGenerator.gen(it.second)
+ stubs.forEach { (first, code) ->
+ val packageName = first.name.substringBeforeLast("/")
+
+ result.add(FileUtil.toFile(it.first), packageName, it.first.name, code)
+ }
+ }
+
+private fun File?.skipTranslating(): Boolean {
+ if (this == null) return true
+
+ val normalizedFile = FileUtil.normalizeFile(this)
+ val fo = FileUtil.toFileObject(normalizedFile) ?: return false
+ val project = ProjectUtils.getKotlinProjectForFileObject(fo) ?: return false
+
+ return !KotlinProjectHelper.hasJavaFiles(project)
+}
+
+private fun FileObject.byteCode(result: AnalysisResultWithProvider? = null,
+ proj: Project? = null): List<ByteArray> {
+ val project = proj ?: ProjectUtils.getKotlinProjectForFileObject(this) ?: return emptyList()
+ val ktFile = ProjectUtils.getKtFile(this) ?: return emptyList()
+ val analysisResult = result ?: KotlinParser.getAnalysisResult(ktFile, project) ?: return emptyList()
+
+ return KotlinLightClassGeneration.getByteCode(this, project, analysisResult.analysisResult)
+}
+
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AbstractBlock.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AbstractBlock.java
new file mode 100644
index 0000000..d045b49
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AbstractBlock.java
@@ -0,0 +1,143 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.google.common.collect.Lists;
+import com.intellij.formatting.ASTBlock;
+import com.intellij.formatting.Alignment;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.ChildAttributes;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Wrap;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.TokenType;
+import java.util.List;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public abstract class AbstractBlock implements ASTBlock {
+
+ private final ASTNode myNode;
+ private final Wrap myWrap;
+ private final Alignment myAlignment;
+ private List<Block> mySubBlocks = null;
+ private Boolean myIncomplete = null;
+ private final List<Block> EMPTY = Lists.newArrayList();
+ protected boolean isBuildIndentsOnly = false;
+
+ public AbstractBlock(ASTNode myNode, Wrap myWrap, Alignment myAlignment) {
+ this.myNode = myNode;
+ this.myWrap = myWrap;
+ this.myAlignment = myAlignment;
+ }
+
+ protected abstract List<Block> buildChildren();
+
+ @Override
+ public ASTNode getNode() {
+ return myNode;
+ }
+
+ @Override
+ public TextRange getTextRange() {
+ return myNode.getTextRange();
+ }
+
+ @Override
+ public List<Block> getSubBlocks() {
+ if (mySubBlocks == null) {
+ mySubBlocks = buildChildren();
+ }
+
+ return mySubBlocks;
+ }
+
+ @Override
+ public Wrap getWrap() {
+ return myWrap;
+ }
+
+ @Override
+ public Indent getIndent() {
+ return null;
+ }
+
+ @Override
+ public Alignment getAlignment() {
+ return myAlignment;
+ }
+
+ @Override
+ public ChildAttributes getChildAttributes(int i) {
+ return new ChildAttributes(getChildIndent(), getFirstChildAlignment());
+ }
+
+ @Override
+ public boolean isIncomplete() {
+ if (myIncomplete == null) {
+ myIncomplete = isIncomplete(getNode());
+ }
+
+ return myIncomplete;
+ }
+
+ private boolean isIncomplete(ASTNode node) {
+ if (node == null) {
+ return false;
+ }
+ ASTNode lastChild = node.getLastChildNode();
+
+ while (lastChild != null && lastChild.getElementType() == TokenType.WHITE_SPACE) {
+ lastChild = lastChild.getTreePrev();
+ }
+
+ if (lastChild == null) {
+ return false;
+ }
+
+ if (lastChild.getElementType() == TokenType.ERROR_ELEMENT) {
+ return true;
+ }
+
+ return isIncomplete(lastChild);
+ }
+
+ private Alignment getFirstChildAlignment() {
+ for (Block subBlock : getSubBlocks()) {
+ if (subBlock.getAlignment() != null) {
+ return subBlock.getAlignment();
+ }
+ }
+
+ return null;
+ }
+
+ protected Indent getChildIndent() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getNode().getText() + " " + getTextRange();
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AlignmentPerTypeStrategy.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AlignmentPerTypeStrategy.java
new file mode 100644
index 0000000..f1cb334
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AlignmentPerTypeStrategy.java
@@ -0,0 +1,67 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.formatting.Alignment;
+import com.intellij.psi.tree.IElementType;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class AlignmentPerTypeStrategy extends KotlinAlignmentStrategy {
+
+ private final Collection<IElementType> targetElementTypes;
+ private final IElementType myParentType;
+ private final boolean myAllowBackwardShift;
+ private final Alignment.Anchor anchor;
+ private final Map<IElementType, Alignment> myAlignments =
+ new HashMap<>();
+
+ public AlignmentPerTypeStrategy(Collection<IElementType> targetElementTypes,
+ IElementType myParentType, boolean myAllowBackwardShift,
+ Alignment.Anchor anchor) {
+ this.targetElementTypes = targetElementTypes;
+ this.myParentType = myParentType;
+ this.myAllowBackwardShift = myAllowBackwardShift;
+ this.anchor = anchor;
+
+ for (IElementType elementType : targetElementTypes) {
+ myAlignments.put(elementType, Alignment.createAlignment(myAllowBackwardShift, anchor));
+ }
+
+ }
+
+ @Override
+ public Alignment getAlignment(IElementType parentType, IElementType childType) {
+ if (myParentType != null && parentType != null && myParentType != parentType) {
+ return null;
+ }
+
+ return myAlignments.get(childType);
+ }
+
+ public void renewAlignment(IElementType elementType) {
+ myAlignments.put(elementType, Alignment.createAlignment(myAllowBackwardShift));
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AlignmentStrategy.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AlignmentStrategy.java
new file mode 100644
index 0000000..e2c500e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/AlignmentStrategy.java
@@ -0,0 +1,74 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import org.jetbrains.kotlin.psi.KtClass;
+import org.jetbrains.kotlin.psi.KtClassInitializer;
+import org.jetbrains.kotlin.psi.KtFunction;
+import org.jetbrains.kotlin.psi.KtPropertyAccessor;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class AlignmentStrategy {
+
+ private static final Set<String> BLOCK_ELEMENT_TYPES = new HashSet<>(Arrays.asList(
+ "IF", "FOR", "WHILE", "CLASS_BODY", "FUNCTION_LITERAL_EXPRESSION",
+ "WHEN", "WHEN_ENTRY", "DO_WHILE", "PROPERTY_ACCESSOR"));
+
+ public AlignmentStrategy(ASTNode parsedFile, int lineIndentation, String lineDelimiter) {
+ }
+
+ public static int computeIndent(ASTNode node) {
+ int indent = 0;
+ while (node != null) {
+ indent = AlignmentStrategy.updateIndent(node, indent);
+ node = node.getTreeParent();
+ }
+
+ return indent;
+ }
+
+ public static int updateIndent(ASTNode node, int indent) {
+ return isBlockElement(node) ? indent + 1 : indent;
+ }
+
+ public static boolean isBlockElement(ASTNode node) {
+ IElementType elementType = node.getElementType();
+ if ("BLOCK".equals(elementType.toString())) {
+ PsiElement parent = node.getPsi().getParent();
+ if (parent instanceof KtFunction || parent instanceof KtClass || parent instanceof KtClassInitializer
+ || parent instanceof KtPropertyAccessor) {
+ return true;
+ }
+ } else if (BLOCK_ELEMENT_TYPES.contains(elementType.toString())) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/IndenterUtil.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/IndenterUtil.java
new file mode 100644
index 0000000..a0299c6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/IndenterUtil.java
@@ -0,0 +1,88 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import org.jetbrains.kotlin.utils.LineEndUtil;
+import org.jetbrains.kotlin.lexer.KtTokens;
+
+public class IndenterUtil {
+ public static final char SPACE_CHAR = ' ';
+ public static final char TAB_CHAR = '\t';
+ public static final String TAB_STRING = Character.toString(TAB_CHAR);
+ public static final int DEFAULT_INDENT = 4;
+
+ public static String createWhiteSpace(int curIndent, int countBreakLines, String lineSeparator) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < countBreakLines; i++) {
+ stringBuilder.append(lineSeparator);
+ }
+
+ String whiteSpace = getIndentString();
+ for (int i = 0; i < curIndent; i++) {
+ stringBuilder.append(whiteSpace);
+ }
+
+ return stringBuilder.toString();
+ }
+
+ public static String getIndentString() {
+ if (isSpacesForTabs()) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < getDefaultIndent(); i++) {
+ result.append(SPACE_CHAR);
+ }
+ return result.toString();
+ } else {
+ return new Character(TAB_CHAR).toString();
+ }
+ }
+
+ public static int getLineSeparatorsOccurences(String text) {
+ int result = 0;
+
+ for (char c : text.toCharArray()) {
+ if (c == LineEndUtil.NEW_LINE_CHAR) {
+ result++;
+ }
+ }
+
+ return result;
+ }
+
+ public static boolean isNewLine(LeafPsiElement psiElement) {
+ return psiElement.getElementType() == KtTokens.WHITE_SPACE && psiElement.getText().contains(LineEndUtil.NEW_LINE_STRING);
+ }
+
+ public static int getDefaultIndent() {
+ return DEFAULT_INDENT;
+ }
+
+ public static boolean isSpacesForTabs() {
+ return true;
+ }
+
+ public static boolean isWhiteSpaceChar(char c) {
+ return c == SPACE_CHAR || c == TAB_CHAR;
+ }
+
+ public static boolean isWhiteSpaceOrNewLine(char c) {
+ return c == SPACE_CHAR || c == TAB_CHAR || c == LineEndUtil.NEW_LINE_CHAR;
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinAlignmentStrategy.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinAlignmentStrategy.java
new file mode 100644
index 0000000..be53053
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinAlignmentStrategy.java
@@ -0,0 +1,90 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+
+import com.google.common.collect.Sets;
+import com.intellij.formatting.Alignment;
+import com.intellij.psi.tree.IElementType;
+import java.util.Collection;
+import java.util.Set;
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public abstract class KotlinAlignmentStrategy {
+
+ private static KotlinAlignmentStrategy nullStrategy = wrap(null, null, null);
+
+ public static KotlinAlignmentStrategy getNullStrategy() {
+ return nullStrategy;
+ }
+
+ public static KotlinAlignmentStrategy wrap(Alignment alignment, IElementType... filterTypes) {
+ return new SharedAlignmentStrategy(alignment, true, filterTypes);
+ }
+
+ public static KotlinAlignmentStrategy wrap(Alignment alignment, boolean ignoreFilterTypes,
+ IElementType... filterTypes) {
+ return new SharedAlignmentStrategy(alignment, ignoreFilterTypes, filterTypes);
+ }
+
+ public static AlignmentPerTypeStrategy createAlignmentPerTypeStrategy(Collection<IElementType> targetTypes,
+ boolean allowBackwardShift) {
+ return new AlignmentPerTypeStrategy(targetTypes, null, allowBackwardShift, Alignment.Anchor.LEFT);
+ }
+
+ public static AlignmentPerTypeStrategy createAlignmentPerStrategy(Collection<IElementType> targetTypes,
+ IElementType parentType, boolean allowBackwardShift, Alignment.Anchor anchor) {
+ Alignment.Anchor a = anchor;
+ if (a == null) {
+ a = Alignment.Anchor.LEFT;
+ }
+ return new AlignmentPerTypeStrategy(targetTypes, parentType, allowBackwardShift, a);
+ }
+
+ public abstract Alignment getAlignment(IElementType parentType, IElementType childType);
+
+ public Alignment getAlignment(IElementType childType) {
+ return getAlignment(null, childType);
+ }
+
+ private static class SharedAlignmentStrategy extends KotlinAlignmentStrategy {
+
+ private final Alignment myAlignment;
+ private final boolean myIgnoreFilterTypes;
+ private final Set<IElementType> myFilterElementTypes;
+
+ SharedAlignmentStrategy(Alignment myAlignment, boolean myIgnoreFilterTypes,
+ IElementType... disabledElementTypes) {
+ this.myAlignment = myAlignment;
+ this.myIgnoreFilterTypes = myIgnoreFilterTypes;
+ this.myFilterElementTypes = Sets.newHashSet(disabledElementTypes);
+ }
+
+ @Override
+ public Alignment getAlignment(IElementType parentType, IElementType childType) {
+ if (myFilterElementTypes.contains(childType) != myIgnoreFilterTypes) {
+ return myAlignment;
+ } else return null;
+ }
+
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinBlock.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinBlock.java
new file mode 100644
index 0000000..09a8287
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinBlock.java
@@ -0,0 +1,186 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.intellij.formatting.ASTBlock;
+import com.intellij.formatting.Alignment;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.ChildAttributes;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Spacing;
+import com.intellij.formatting.Wrap;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.tree.IElementType;
+import java.util.List;
+import org.jetbrains.kotlin.KtNodeTypes;
+import org.jetbrains.kotlin.idea.formatter.CommonAlignmentStrategy;
+import org.jetbrains.kotlin.idea.formatter.KotlinCommonBlock;
+import org.jetbrains.kotlin.idea.formatter.KotlinSpacingBuilder;
+import org.jetbrains.kotlin.lexer.KtTokens;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinBlock extends AbstractBlock {
+
+ private final ASTNode node;
+ private final CommonAlignmentStrategy myAlignmentStrategy;
+ private final Indent indent;
+ private final Wrap wrap;
+ private final CodeStyleSettings mySettings;
+ private final KotlinSpacingBuilder mySpacingBuilder;
+ private KotlinCommonBlock kotlinDelegationBlock;
+
+ public KotlinBlock(ASTNode node, CommonAlignmentStrategy myAlignmentStrategy,
+ Indent indent, Wrap wrap, CodeStyleSettings mySettings,
+ KotlinSpacingBuilder mySpacingBuilder) {
+ super(node, wrap, myAlignmentStrategy.getAlignment(node));
+ this.node = node;
+ this.myAlignmentStrategy = myAlignmentStrategy;
+ this.indent = indent;
+ this.wrap = wrap;
+ this.mySettings = mySettings;
+ this.mySpacingBuilder = mySpacingBuilder;
+ kotlinDelegationBlock = getKotlinCommonBlock();
+ }
+
+ private KotlinCommonBlock getKotlinCommonBlock() {
+ return new KotlinCommonBlock(node, mySettings, mySpacingBuilder,myAlignmentStrategy) {
+
+ @Override
+ protected Block createBlock(ASTNode node, CommonAlignmentStrategy alignmentStrategy,
+ Indent indent, Wrap wrap, CodeStyleSettings css, KotlinSpacingBuilder ksb) {
+ return new KotlinBlock(node, alignmentStrategy, indent,
+ wrap, mySettings, mySpacingBuilder);
+ }
+
+ @Override
+ protected ASTBlock createSyntheticSpacingNodeBlock(ASTNode node) {
+ return new AbstractBlock(node, null, null) {
+ @Override
+ protected List<Block> buildChildren() {
+ return Lists.newArrayList();
+ }
+
+ @Override
+ public Spacing getSpacing(Block block, Block block1) {
+ return null;
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return false;
+ }
+ };
+ }
+
+ @Override
+ protected List<Block> getSubBlocks() {
+ return KotlinBlock.super.getSubBlocks();
+ }
+
+ @Override
+ protected ChildAttributes getSuperChildAttributes(int newChildIndex) {
+ return KotlinBlock.super.getChildAttributes(newChildIndex);
+ }
+
+ @Override
+ protected boolean isIncompleteInSuper() {
+ return KotlinBlock.super.isIncomplete();
+ }
+
+ @Override
+ protected CommonAlignmentStrategy getAlignmentForCaseBranch(boolean shouldAlignInColumns) {
+ if (shouldAlignInColumns) {
+ return NodeAlignmentStrategy.fromTypes(
+ KotlinAlignmentStrategy.createAlignmentPerStrategy(Sets.newHashSet((IElementType) KtTokens.ARROW),
+ KtNodeTypes.WHEN_ENTRY, true, null));
+ } else {
+ return NodeAlignmentStrategy.getNullStrategy();
+ }
+ }
+
+ @Override
+ protected Alignment getAlignment() {
+ return KotlinBlock.super.getAlignment();
+ }
+
+ @Override
+ protected CommonAlignmentStrategy createAlignmentStrategy(boolean alignOption,
+ Alignment defaultAlignment) {
+ return NodeAlignmentStrategy.fromTypes(KotlinAlignmentStrategy.wrap(
+ createAlignment(alignOption, defaultAlignment)));
+ }
+
+ @Override
+ protected CommonAlignmentStrategy getNullAlignmentStrategy() {
+ return NodeAlignmentStrategy.fromTypes(KotlinAlignmentStrategy.wrap(null));
+ }
+
+ private Alignment createAlignment(boolean alignOption, Alignment defaultAlignment) {
+ if (alignOption) {
+ return createAlignmentOrDefault(null, defaultAlignment);
+ } else return defaultAlignment;
+ }
+
+ private Alignment createAlignmentOrDefault(Alignment base, Alignment defaultAlignment) {
+ if (defaultAlignment != null) {
+ return defaultAlignment;
+ }
+ if (base == null) {
+ return Alignment.createAlignment();
+ } else {
+ return Alignment.createChildAlignment(base);
+ }
+ }
+
+ };
+ }
+
+ @Override
+ public Indent getIndent() {
+ return indent;
+ }
+
+
+ @Override
+ protected List<Block> buildChildren() {
+ return kotlinDelegationBlock.buildChildren();
+ }
+
+ @Override
+ public Spacing getSpacing(Block child1, Block child2) {
+ return mySpacingBuilder.getSpacing(this, child1, child2);
+ }
+
+ @Override
+ public ChildAttributes getChildAttributes(int newChildIndex) {
+ return kotlinDelegationBlock.getChildAttributes(newChildIndex);
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return kotlinDelegationBlock.isLeaf();
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinFormatter.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinFormatter.java
new file mode 100644
index 0000000..e458541
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinFormatter.java
@@ -0,0 +1,94 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.formatting.DependentSpacingRule;
+import com.intellij.formatting.FormatterImpl;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Spacing;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.formatter.FormatterUtil;
+import com.intellij.formatting.DependantSpacingImpl;
+import org.jetbrains.kotlin.idea.formatter.KotlinSpacingBuilderUtil;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.psi.KtPsiFactory;
+import org.jetbrains.kotlin.idea.formatter.KotlinSpacingRulesKt;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinFormatter {
+
+ private final String source;
+ private final String fileName;
+ private final KtPsiFactory psiFactory;
+ private final String lineSeparator;
+ private final KtFile ktFile;
+
+ public KotlinFormatter(String source, String fileName, KtPsiFactory psiFactory, String lineSeparator) {
+ this.source = source;
+ this.fileName = fileName;
+ this.psiFactory = psiFactory;
+ this.lineSeparator = lineSeparator;
+ ktFile = KotlinFormatterUtils.createKtFile(source, psiFactory, fileName);
+ }
+
+ public String formatCode() {
+ new FormatterImpl();
+ KotlinBlock rootBlock = new KotlinBlock(ktFile.getNode(),
+ NodeAlignmentStrategy.getNullStrategy(),
+ Indent.getNoneIndent(),
+ null,
+ KotlinFormatterUtils.getSettings(),
+ KotlinSpacingRulesKt.createSpacingBuilder(
+ KotlinFormatterUtils.getSettings(), KotlinSpacingBuilderUtilImpl.INSTANCE));
+ return KotlinFormatterUtils.reformatAll(ktFile, rootBlock,
+ KotlinFormatterUtils.getSettings(), source);
+ }
+
+ static class KotlinSpacingBuilderUtilImpl implements KotlinSpacingBuilderUtil {
+
+ public static KotlinSpacingBuilderUtilImpl INSTANCE =
+ new KotlinSpacingBuilderUtilImpl();
+
+ private KotlinSpacingBuilderUtilImpl(){}
+
+ @Override
+ public Spacing createLineFeedDependentSpacing(int minSpaces,
+ int maxSpaces, int minimumLineFeeds, boolean keepLineBreaks,
+ int keepBlankLines, TextRange dependency, DependentSpacingRule rule) {
+ return new DependantSpacingImpl(minSpaces, maxSpaces, dependency, keepLineBreaks,
+ keepBlankLines, rule);
+ }
+
+ @Override
+ public ASTNode getPreviousNonWhitespaceLeaf(ASTNode node) {
+ return FormatterUtil.getPreviousNonWhitespaceLeaf(node);
+ }
+
+ @Override
+ public boolean isWhitespaceOrEmpty(ASTNode node) {
+ return FormatterUtil.isWhitespaceOrEmpty(node);
+ }
+
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinFormatterUtils.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinFormatterUtils.java
new file mode 100644
index 0000000..78920b1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinFormatterUtils.java
@@ -0,0 +1,160 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.formatting.Block;
+import com.intellij.formatting.FormatTextRanges;
+import com.intellij.formatting.FormatterImpl;
+import com.intellij.formatting.Indent;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.impl.DocumentImpl;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptions;
+import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.kotlin.formatting.KotlinFormatter.KotlinSpacingBuilderUtilImpl;
+import org.jetbrains.kotlin.idea.formatter.KotlinSpacingRulesKt;
+import org.jetbrains.kotlin.model.KotlinEnvironment;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.psi.KtPsiFactory;
+import org.jetbrains.kotlin.utils.LineEndUtil;
+import org.netbeans.api.project.Project;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinFormatterUtils {
+
+ private static final CodeStyleSettings settings = new CodeStyleSettings(true);
+
+ public static CodeStyleSettings getSettings() {
+ return settings;
+ }
+
+ public static KtPsiFactory createPsiFactory(Project project) {
+ KotlinEnvironment environment = KotlinEnvironment.Companion.getEnvironment(project);
+ return new KtPsiFactory(environment.getProject());
+ }
+
+ public static String formatCode(String source, String fileName, Project project, String lineSeparator) {
+ return formatCode(source, fileName, createPsiFactory(project), lineSeparator);
+ }
+
+ public static String formatCode(String source, String fileName, KtPsiFactory psiFactory, String lineSeparator) {
+ return new KotlinFormatter(source, fileName, psiFactory, lineSeparator).formatCode();
+ }
+
+ public static String reformatAll(KtFile containingFile, Block rootBlock,
+ CodeStyleSettings settings, String source ) {
+ return formatRange(containingFile, rootBlock, settings, source, containingFile.getTextRange());
+ }
+
+ public static String formatRange(String source, NetBeansDocumentRange range,
+ KtPsiFactory psiFactory, String fileName) {
+ return formatRange(source, range.toPsiRange(source), psiFactory, fileName);
+ }
+
+ public static String formatRange(String source, TextRange range, KtPsiFactory psiFactory, String fileName) {
+ KtFile ktFile = createKtFile(source, psiFactory, fileName);
+ Block rootBlock = new KotlinBlock(ktFile.getNode(),
+ NodeAlignmentStrategy.getNullStrategy(),
+ Indent.getNoneIndent(),
+ null,
+ settings,
+ KotlinSpacingRulesKt.createSpacingBuilder(settings, KotlinSpacingBuilderUtilImpl.INSTANCE));
+ return formatRange(ktFile, rootBlock, settings, source, range);
+ }
+
+ private static String formatRange(KtFile containingFile, Block rootBlock,
+ CodeStyleSettings settings, String source, TextRange range) {
+ NetBeansDocumentFormattingModel formattingModel =
+ buildModel(containingFile, rootBlock, settings, source, false);
+ FormatTextRanges ranges = new FormatTextRanges(range, true);
+ new FormatterImpl().format(formattingModel, settings, settings.getIndentOptions(), ranges, false);
+
+ return formattingModel.getNewText();
+ }
+
+ private static void initializeSettings(IndentOptions options) {
+ options.USE_TAB_CHARACTER = !IndenterUtil.isSpacesForTabs();
+ options.INDENT_SIZE = IndenterUtil.getDefaultIndent();
+ options.TAB_SIZE = IndenterUtil.getDefaultIndent();
+ }
+
+ private static NetBeansDocumentFormattingModel buildModel(KtFile ktFile,
+ Block rootBlock, CodeStyleSettings settings, String source,
+ boolean forLineIndentation) {
+ initializeSettings(settings.getIndentOptions());
+ NetBeansFormattingModel formattingDocumentModel =
+ new NetBeansFormattingModel(
+ new DocumentImpl(ktFile.getViewProvider().getContents(), true),
+ ktFile, settings, forLineIndentation);
+
+ return new NetBeansDocumentFormattingModel(
+ ktFile, rootBlock, formattingDocumentModel, source, settings);
+ }
+
+ // ???
+ public static Document getMockDocument(Document document) {
+ return document;
+ }
+
+ public static KtFile createKtFile(String source, KtPsiFactory psiFactory, String fileName) {
+ return psiFactory.createFile(fileName, StringUtil.convertLineSeparators(source));
+ }
+
+ private static TextRange getSignificantRange(KtFile file, int offset) {
+ PsiElement elementAtOffset = file.findElementAt(offset);
+ if (elementAtOffset == null) {
+ int significantRangeStart = CharArrayUtil.shiftBackward(file.getText(), offset - 1, "\r\t ");
+ return new TextRange(Math.max(significantRangeStart, 0), offset);
+ }
+
+ return elementAtOffset.getTextRange();
+ }
+
+ public static String adjustIndent(KtFile containingFile, Block rootBlock,
+ CodeStyleSettings settings, int offset, String document) {
+ NetBeansDocumentFormattingModel model =
+ buildModel(containingFile, rootBlock, settings, document, true);
+ new FormatterImpl().adjustLineIndent(model, settings, settings.getIndentOptions(),
+ offset, getSignificantRange(containingFile, offset));
+
+ return model.getNewText();
+ }
+
+ public static class NetBeansDocumentRange {
+ private final int startOffset, endOffset;
+
+ public NetBeansDocumentRange(int start, int end) {
+ startOffset = start;
+ endOffset = end;
+ }
+
+ public TextRange toPsiRange(String source) {
+ int startPsiOffset = LineEndUtil.convertCrToDocumentOffset(source, startOffset);
+ int endPsiOffset = LineEndUtil.convertCrToDocumentOffset(source, endOffset);
+
+ return new TextRange(startPsiOffset, endPsiOffset);
+ }
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinIndentStrategy.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinIndentStrategy.java
new file mode 100644
index 0000000..22a0536
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/KotlinIndentStrategy.java
@@ -0,0 +1,271 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.formatting.FormatterImpl;
+import com.intellij.formatting.Indent;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.StyledDocument;
+import org.jetbrains.kotlin.idea.formatter.KotlinSpacingRulesKt;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.psi.KtPsiFactory;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.editor.NbEditorUtilities;
+import org.netbeans.modules.editor.indent.spi.Context;
+import org.openide.filesystems.FileObject;
+import org.openide.text.Line;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinIndentStrategy {
+
+ private static final char OPENING_BRACE_CHAR = '{';
+ private static final char CLOSING_BRACE_CHAR = '}';
+ private static final String CLOSING_BRACE_STRING = Character.toString(CLOSING_BRACE_CHAR);
+ private static final String OPENING_BRACE_STRING = Character.toString(OPENING_BRACE_CHAR);
+
+ private final StyledDocument doc;
+ private final FileObject file;
+ private int caretOffset;
+ private int offset;
+
+ public KotlinIndentStrategy(StyledDocument doc, int offset) {
+ new FormatterImpl();
+ this.doc = doc;
+ this.file = ProjectUtils.getFileObjectForDocument(doc);
+ this.offset = offset;
+ caretOffset = offset;
+ }
+
+ public KotlinIndentStrategy(Context context) {
+ this((StyledDocument) context.document(), context.caretOffset());
+ }
+
+ public int addIndent() throws BadLocationException {
+ if (offset == 1) {
+ return offset;
+ }
+ if (offset == doc.getLength()) {
+ offset--;
+ }
+ String text = doc.getText(0, doc.getLength());
+ String commandText = String.valueOf((text).charAt(offset));
+
+ if (isBeforeCloseBrace(text, offset, text.length()) && isAfterOpenBrace(text, offset, 0)) {
+ return autoEditAfterOpenBraceAndBeforeCloseBrace(text);
+ } else if(CLOSING_BRACE_STRING.equals(commandText)) {
+ return autoEditBeforeCloseBrace(text);
+ } else {
+ return autoEdit(text);
+ }
+ }
+
+ private int autoEdit(String text) throws BadLocationException {
+ StringBuilder textToFormat = new StringBuilder();
+ textToFormat.append(text.substring(0, caretOffset));
+
+ char charToInsert = ' ';
+ if (isAfterEqualityOrOpenBrace(textToFormat.toString(), textToFormat.length())) {
+ charToInsert = '1';
+ }
+ textToFormat.append(charToInsert).
+ append(text.substring(caretOffset));
+
+ String indent = getIndent(textToFormat.toString(), caretOffset);
+ doc.insertString(caretOffset, indent, null);
+
+ return caretOffset + indent.length();
+ }
+
+ private int autoEditAfterOpenBraceAndBeforeCloseBrace(String text) throws BadLocationException {
+ int diff = findEndOfWhiteSpaceAfter(text, offset, text.length()) - offset;
+ String indent = getIndent(text, caretOffset);
+ StringBuilder builder = new StringBuilder();
+ builder.append(indent).append(" ").append('\n').append(indent);
+ doc.remove(caretOffset, diff);
+ doc.insertString(caretOffset, builder.toString(), null);
+ setDocumentOffset(indent.length() + 4);
+
+ return caretOffset + indent.length() + 4;
+ }
+
+ private int autoEditBeforeCloseBrace(String text) throws BadLocationException {
+ if (isNewLineBefore(text, caretOffset)) {
+ StringBuilder oldText = new StringBuilder();
+
+ oldText.append(text.substring(0, caretOffset - 1));
+ oldText.append(CLOSING_BRACE_STRING).append(" ");
+ oldText.append(text.substring(caretOffset + 1));
+
+ if (oldText.charAt(caretOffset - 2) == '\n') {
+ return caretOffset;
+ }
+
+ String indent = getIndent(oldText.toString(), caretOffset);
+ doc.insertString(caretOffset, indent, null);
+ return caretOffset + indent.length();
+ }
+
+ return caretOffset;
+ }
+
+ private String getIndent(String text, int offset) throws BadLocationException {
+ Project project = ProjectUtils.getKotlinProjectForFileObject(file);
+ if (project == null) {
+ return "";
+ }
+ KtPsiFactory psiFactory = KotlinFormatterUtils.createPsiFactory(project);
+ KtFile ktFile = KotlinFormatterUtils.createKtFile(text, psiFactory, file.getName());
+
+ CodeStyleSettings settings = KotlinFormatterUtils.getSettings();
+ KotlinBlock rootBlock = new KotlinBlock(ktFile.getNode(),
+ NodeAlignmentStrategy.getNullStrategy(),
+ Indent.getNoneIndent(),
+ null,
+ settings,
+ KotlinSpacingRulesKt.createSpacingBuilder(
+ settings, KotlinFormatter.KotlinSpacingBuilderUtilImpl.INSTANCE));
+
+ String newText = KotlinFormatterUtils.adjustIndent(ktFile, rootBlock, settings, offset, text);
+ if (newText == null) {
+ return "";
+ }
+
+ if (offset >= newText.length()) {
+ return "";
+ }
+ newText = newText.substring(offset);
+
+ int endOfWhiteSpace = findEndOfWhiteSpaceAfter(newText, 0, newText.length());
+ String toReturn = newText.substring(0, endOfWhiteSpace);
+
+ return toReturn;
+ }
+
+ private static int findEndOfWhiteSpaceAfter(String document, int offset, int end) throws BadLocationException {
+ while (offset < end) {
+ if (!IndenterUtil.isWhiteSpaceChar(document.charAt(offset))) {
+ return offset;
+ }
+
+ offset++;
+ }
+
+ return end;
+ }
+
+ private static int findEndOfWhiteSpaceBefore(String document, int offset, int start) throws BadLocationException {
+ while (offset >= start) {
+ if (!IndenterUtil.isWhiteSpaceChar(document.charAt(offset))) {
+ return offset;
+ }
+
+ offset--;
+ }
+
+ return start;
+ }
+
+ private boolean isAfterEqualityOrOpenBrace(String text, int offset) {
+ int curOffset = offset - 2;
+ while (curOffset > 0) {
+ char charAtCurrentOffset = text.charAt(curOffset);
+ if (charAtCurrentOffset == '=' || charAtCurrentOffset == '{') {
+ return true;
+ } else if (charAtCurrentOffset != ' ') {
+ return false;
+ }
+ curOffset--;
+ }
+
+ return false;
+ }
+
+ private static int findEndOfWhiteSpaceBefore(String text, int offset) {
+ int curOffset = offset - 2;
+ while (curOffset >= 0) {
+ if (!IndenterUtil.isWhiteSpaceChar(text.charAt(curOffset))) return curOffset;
+
+ curOffset--;
+ }
+
+ return offset;
+ }
+
+ private static boolean isAfterOpenBrace(String document, int offset, int startLineOffset) throws BadLocationException {
+ int nonEmptyOffset = findEndOfWhiteSpaceBefore(document, offset);
+
+ return document.charAt(nonEmptyOffset) == OPENING_BRACE_CHAR;
+ }
+
+ private static boolean isBeforeCloseBrace(String document, int offset, int endLineOffset) throws BadLocationException {
+ int nonEmptyOffset = findEndOfWhiteSpaceAfter(document, offset, endLineOffset);
+ if (nonEmptyOffset == document.length()) {
+ nonEmptyOffset--;
+ }
+
+ return document.charAt(nonEmptyOffset) == CLOSING_BRACE_CHAR;
+ }
+
+ private static boolean isNewLineBefore(String document, int offset) {
+ offset--;
+ char prev = IndenterUtil.SPACE_CHAR;
+ StringBuilder bufBefore = new StringBuilder(prev);
+ while (IndenterUtil.isWhiteSpaceChar(prev) && offset > 0) {
+ prev = document.charAt(offset--);
+ bufBefore.append(prev);
+ }
+
+ return containsNewLine(bufBefore.toString());
+ }
+
+ private static boolean startsWithNewLine(String text) {
+ return text.startsWith("\n");
+ }
+
+ private static boolean containsNewLine(String text) {
+ return text.contains("\n");
+ }
+
+ private static int findEndOfWhiteSpace(String text, int offset) {
+ while (offset > 0) {
+ char c = text.charAt(offset);
+ if (!IndenterUtil.isWhiteSpaceChar(c)) {
+ return offset;
+ }
+
+ offset--;
+ }
+
+ return offset;
+ }
+
+ private static boolean isNewLine(String text) {
+ return "\n".equals(text);
+ }
+
+ private void setDocumentOffset(int column) {
+ Line line = NbEditorUtilities.getLine(doc, offset, false);
+ line.show(Line.ShowOpenType.NONE,Line.ShowVisibilityType.NONE, column);
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NetBeansDocumentFormattingModel.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NetBeansDocumentFormattingModel.java
new file mode 100644
index 0000000..cb00153
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NetBeansDocumentFormattingModel.java
@@ -0,0 +1,249 @@
+package org.jetbrains.kotlin.formatting;
+
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ ******************************************************************************
+ */
+import com.intellij.formatting.Block;
+import com.intellij.formatting.FormattingDocumentModel;
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.impl.source.SourceTreeToPsiMap;
+
+import com.intellij.formatting.FormattingModelEx;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.text.BadLocationException;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class NetBeansDocumentFormattingModel implements FormattingModelEx {
+
+ private String newText;
+ private final Project myProject;
+ private final ASTNode myASTNode;
+ private final NetBeansFormattingModel myDocumentModel;
+ private final Block myRootBlock;
+ protected boolean myCanModifyAllWhiteSpaces = false;
+ private final String source;
+ private final List<ReplaceEdit> edits = new ArrayList<>();
+ private final CodeStyleSettings settings;
+
+ public NetBeansDocumentFormattingModel(PsiFile file, Block rootBlock,
+ NetBeansFormattingModel documentModel, String source,
+ CodeStyleSettings settings) {
+ myASTNode = SourceTreeToPsiMap.psiElementToTree(file);
+ myDocumentModel = documentModel;
+ myRootBlock = rootBlock;
+ myProject = file.getProject();
+ this.source = source;
+ this.settings = settings;
+ }
+
+ @Override
+ public Block getRootBlock() {
+ return myRootBlock;
+ }
+
+ @Override
+ public FormattingDocumentModel getDocumentModel() {
+ return myDocumentModel;
+ }
+
+ @Override
+ public TextRange replaceWhiteSpace(TextRange textRange, String whiteSpace) {
+ return replaceWhiteSpace(textRange, null, whiteSpace);
+ }
+
+ @Override
+ public TextRange replaceWhiteSpace(TextRange textRange, ASTNode nodeAfter, String whiteSpace) {
+ CharSequence whiteSpaceToUse = getDocumentModel().adjustWhiteSpaceIfNecessary(whiteSpace,
+ textRange.getStartOffset(), textRange.getEndOffset(), nodeAfter, false);
+
+ replace(textRange, whiteSpaceToUse.toString());
+ return textRange;
+ }
+
+ @Override
+ public TextRange shiftIndentInsideRange(ASTNode node, TextRange range, int indent) {
+ try {
+ shiftIndentInside(range, indent);
+ return range;
+ } catch (BadLocationException e) {
+ }
+
+ return null;
+ }
+
+ private int shiftIndentInside(final TextRange elementRange, final int shift) throws BadLocationException {
+ final StringBuilder buffer = new StringBuilder();
+ StringBuilder afterWhiteSpace = new StringBuilder();
+ int whiteSpaceLength = 0;
+ boolean insideWhiteSpace = true;
+ int line = 0;
+ for (int i = elementRange.getStartOffset(); i < elementRange.getEndOffset(); i++) {
+ final char c = source.charAt(i);
+ switch (c) {
+ case '\n':
+ if (line > 0) {
+ createWhiteSpace(whiteSpaceLength + shift, buffer);
+ }
+ buffer.append(afterWhiteSpace.toString());
+ insideWhiteSpace = true;
+ whiteSpaceLength = 0;
+ afterWhiteSpace = new StringBuilder();
+ buffer.append(c);
+ line++;
+ break;
+ case ' ':
+ if (insideWhiteSpace) {
+ whiteSpaceLength += 1;
+ } else {
+ afterWhiteSpace.append(c);
+ }
+ break;
+ case '\t':
+ if (insideWhiteSpace) {
+ whiteSpaceLength += getIndentOptions().TAB_SIZE;
+ } else {
+ afterWhiteSpace.append(c);
+ }
+
+ break;
+ default:
+ insideWhiteSpace = false;
+ afterWhiteSpace.append(c);
+ }
+ }
+ if (line > 0) {
+ createWhiteSpace(whiteSpaceLength + shift, buffer);
+ }
+ buffer.append(afterWhiteSpace.toString());
+
+ replace(elementRange, buffer.toString());
+
+ return buffer.length();
+ }
+
+ private void createWhiteSpace(final int whiteSpaceLength, StringBuilder buffer) {
+ if (whiteSpaceLength < 0) {
+ return;
+ }
+
+ StringUtil.repeatSymbol(buffer, ' ', whiteSpaceLength);
+ }
+
+ private CommonCodeStyleSettings.IndentOptions getIndentOptions() {
+ return settings.getIndentOptions();
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ @Nullable
+ public static String mergeWsWithCdataMarker(String whiteSpace, final String s, final int cdataPos) {
+ final int firstCrInGeneratedWs = whiteSpace.indexOf('\n');
+ final int secondCrInGeneratedWs = firstCrInGeneratedWs != -1
+ ? whiteSpace.indexOf('\n', firstCrInGeneratedWs + 1) : -1;
+ final int firstCrInPreviousWs = s.indexOf('\n');
+ final int secondCrInPreviousWs = firstCrInPreviousWs != -1 ? s.indexOf('\n', firstCrInPreviousWs + 1) : -1;
+
+ boolean knowHowToModifyCData = false;
+
+ if (secondCrInPreviousWs != -1 && secondCrInGeneratedWs != -1 && cdataPos > firstCrInPreviousWs
+ && cdataPos < secondCrInPreviousWs) {
+ whiteSpace = whiteSpace.substring(0, secondCrInGeneratedWs)
+ + s.substring(firstCrInPreviousWs + 1, secondCrInPreviousWs)
+ + whiteSpace.substring(secondCrInGeneratedWs);
+ knowHowToModifyCData = true;
+ }
+ if (!knowHowToModifyCData) {
+ whiteSpace = null;
+ }
+ return whiteSpace;
+ }
+
+ private void replace(TextRange range, String whiteSpace) {
+ String convertedWhiteSpace = StringUtil.convertLineSeparators(whiteSpace, "\n");
+ int startOffset = convertOffset(range.getStartOffset());
+ int endOffset = convertOffset(range.getEndOffset());
+ ReplaceEdit edit = new ReplaceEdit(startOffset, endOffset - startOffset, convertedWhiteSpace);
+ edits.add(edit);
+ }
+
+ private int convertOffset(int offset) {
+ return offset;
+ }
+
+ @Override
+ public void commitChanges() {
+ StringBuilder newTextBuilder = new StringBuilder();
+ int offset = 0;
+ if (edits.isEmpty()) {
+ newText = source;
+ return;
+ }
+
+ for (ReplaceEdit edit : edits) {
+ newTextBuilder.append(source.substring(offset, edit.startOffset));
+ newTextBuilder.append(edit.replaceStr);
+ offset = edit.startOffset+edit.length;
+ }
+
+ newTextBuilder.append(source.substring(offset));
+
+ newText = newTextBuilder.toString();
+ }
+
+ public String getNewText() {
+ return newText;
+ }
+
+ private static class ReplaceEdit {
+
+ public int getStartOffset() {
+ return startOffset;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public String getReplaceStr() {
+ return replaceStr;
+ }
+ private final int startOffset;
+ private final int length;
+ private final String replaceStr;
+
+ public ReplaceEdit(int startOffset, int endOffset, String replaceStr) {
+ this.startOffset = startOffset;
+ this.length = endOffset;
+ this.replaceStr = replaceStr;
+ }
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NetBeansFormattingModel.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NetBeansFormattingModel.java
new file mode 100644
index 0000000..daf9b5c
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NetBeansFormattingModel.java
@@ -0,0 +1,172 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import com.intellij.formatting.FormattingDocumentModel;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.formatter.WhiteSpaceFormattingStrategy;
+import com.intellij.psi.formatter.WhiteSpaceFormattingStrategyFactory;
+
+public class NetBeansFormattingModel implements FormattingDocumentModel {
+
+ private final WhiteSpaceFormattingStrategy myWhiteSpaceStrategy;
+
+ @NotNull
+ private final Document myDocument;
+ private final PsiFile myFile;
+
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.FormattingDocumentModelImpl");
+ private final CodeStyleSettings mySettings;
+
+ private final int maxDepthToCheck = 10;
+ private final String applyChangeStateClassName = "com.intellij.formatting.FormatProcessor$ApplyChangesState";
+ private final String prepareMethodName = "prepare";
+
+ private final boolean forLineIndentation;
+
+ public NetBeansFormattingModel(
+ @NotNull final Document document,
+ PsiFile file,
+ CodeStyleSettings settings,
+ boolean forLineIndentation) {
+ myDocument = document;
+ myFile = file;
+ if (file != null) {
+ Language language = file.getLanguage();
+ myWhiteSpaceStrategy = WhiteSpaceFormattingStrategyFactory.getStrategy(language);
+ } else {
+ myWhiteSpaceStrategy = WhiteSpaceFormattingStrategyFactory.getStrategy();
+ }
+ mySettings = settings;
+ this.forLineIndentation = forLineIndentation;
+ }
+
+ @Nullable
+ public static Document getDocumentToBeUsedFor(final PsiFile file) {
+ final Project project = file.getProject();
+ final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
+ if (document == null)
+ return null;
+ if (PsiDocumentManager.getInstance(project).isUncommited(document))
+ return null;
+
+ return document;
+ }
+
+ @Override
+ public int getLineNumber(int offset) {
+ if (offset > myDocument.getTextLength()) {
+ LOG.error(String.format("Invalid offset detected (%d). Document length: %d. Target file: %s", offset,
+ myDocument.getTextLength(), myFile));
+ }
+ return myDocument.getLineNumber(offset);
+ }
+
+ @Override
+ public int getLineStartOffset(int line) {
+ return myDocument.getLineStartOffset(line);
+ }
+
+ @Override
+ public CharSequence getText(final TextRange textRange) {
+ if (textRange.getStartOffset() < 0 || textRange.getEndOffset() > myDocument.getTextLength()) {
+ LOG.error(String.format(
+ "Please submit a ticket to the tracker and attach current source file to it!%nInvalid processing detected: given text "
+ + "range (%s) targets non-existing regions (the boundaries are [0; %d)). File's language: %s",
+ textRange, myDocument.getTextLength(), myFile.getLanguage()));
+ }
+ return myDocument.getCharsSequence().subSequence(textRange.getStartOffset(), textRange.getEndOffset());
+ }
+
+ @Override
+ public int getTextLength() {
+ return myDocument.getTextLength();
+ }
+
+ @NotNull
+ @Override
+ public Document getDocument() {
+ if (forLineIndentation) {
+ return myDocument;
+ }
+
+ int i = 0;
+ for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
+ if (i > maxDepthToCheck) {
+ break;
+ }
+
+ if (prepareMethodName.equals(element.getMethodName()) && applyChangeStateClassName.equals(element.getClassName())) {
+ return KotlinFormatterUtils.getMockDocument(myDocument);
+ }
+
+ i++;
+ }
+ return myDocument;
+ }
+
+ public PsiFile getFile() {
+ return myFile;
+ }
+
+ @Override
+ public boolean containsWhiteSpaceSymbolsOnly(int startOffset, int endOffset) {
+ WhiteSpaceFormattingStrategy strategy = myWhiteSpaceStrategy;
+ if (strategy.check(myDocument.getCharsSequence(), startOffset, endOffset) >= endOffset) {
+ return true;
+ }
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public CharSequence adjustWhiteSpaceIfNecessary(@NotNull CharSequence whiteSpaceText, int startOffset,
+ int endOffset, @Nullable ASTNode nodeAfter, boolean changedViaPsi) {
+ if (!changedViaPsi) {
+ return myWhiteSpaceStrategy.adjustWhiteSpaceIfNecessary(whiteSpaceText, myDocument.getCharsSequence(),
+ startOffset, endOffset, mySettings, nodeAfter);
+ }
+
+ final PsiElement element = myFile.findElementAt(startOffset);
+ if (element == null) {
+ return whiteSpaceText;
+ } else {
+ return myWhiteSpaceStrategy.adjustWhiteSpaceIfNecessary(whiteSpaceText, element, startOffset, endOffset,
+ mySettings);
+ }
+ }
+
+ public static boolean canUseDocumentModel(@NotNull Document document, @NotNull PsiFile file) {
+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(file.getProject());
+ return !psiDocumentManager.isUncommited(document) && !psiDocumentManager.isDocumentBlockedByPsi(document)
+ && file.getText().equals(document.getText());
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NodeAlignmentStrategy.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NodeAlignmentStrategy.java
new file mode 100644
index 0000000..23731bb
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/formatting/NodeAlignmentStrategy.java
@@ -0,0 +1,60 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.formatting;
+
+import com.intellij.formatting.Alignment;
+import com.intellij.lang.ASTNode;
+import org.jetbrains.kotlin.idea.formatter.CommonAlignmentStrategy;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public abstract class NodeAlignmentStrategy extends CommonAlignmentStrategy {
+
+ private static NodeAlignmentStrategy nullStrategy = fromTypes(KotlinAlignmentStrategy.getNullStrategy());
+
+ public static NodeAlignmentStrategy fromTypes(KotlinAlignmentStrategy strategy) {
+ return new AlignmentStrategyWrapper(strategy);
+ }
+
+ public static NodeAlignmentStrategy getNullStrategy(){
+ return nullStrategy;
+ }
+
+ private static class AlignmentStrategyWrapper extends NodeAlignmentStrategy {
+ private final KotlinAlignmentStrategy internalStrategy;
+
+ AlignmentStrategyWrapper(KotlinAlignmentStrategy internalStrategy) {
+ this.internalStrategy = internalStrategy;
+ }
+
+ @Override
+ public Alignment getAlignment(ASTNode node) {
+ ASTNode parent = node.getTreeParent();
+ if (parent != null) {
+ return internalStrategy.getAlignment(parent.getElementType(), node.getElementType());
+ }
+
+ return internalStrategy.getAlignment(node.getElementType());
+ }
+
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/KotlinTokenScanner.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/KotlinTokenScanner.kt
new file mode 100644
index 0000000..f03ec33
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/KotlinTokenScanner.kt
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinToken
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinTokenId
+import org.jetbrains.kotlin.psi.KtFile
+import org.netbeans.spi.lexer.LexerInput
+
+class KotlinTokenScanner(private val input: LexerInput?, text: String? = null) {
+
+ private val kotlinTokensFactory = KotlinTokensFactory()
+ private val ktFile: KtFile?
+ val tokens = arrayListOf<KotlinToken<KotlinTokenId>>()
+
+ init {
+ ktFile = if (text == null) {
+ KotlinPsiManager.getParsedKtFileForSyntaxHighlighting(getTextToParse())
+ } else {
+ KotlinPsiManager.getParsedKtFileForSyntaxHighlighting(text)
+ }
+ createListOfKotlinTokens()
+ }
+
+ constructor(text: String) : this(null, text)
+
+ private fun getTextToParse(): String {
+ if (input == null) return ""
+ val builder = StringBuilder()
+ var character: Int
+
+ do {
+ character = input.read()
+ builder.append(character.toChar())
+ } while (character != LexerInput.EOF)
+
+ input.backup(input.readLengthEOF())
+ return builder.toString()
+ }
+
+ private fun createListOfKotlinTokens() {
+ tokens.clear()
+ if (ktFile == null) return
+
+ var lastElement: PsiElement?
+ var offset = 0
+
+ while(true) {
+ lastElement = ktFile.findElementAt(offset)
+ if (lastElement != null) {
+ offset = lastElement.textRange.endOffset
+ val tokenType = kotlinTokensFactory.getToken(lastElement)
+ tokens.add(KotlinToken(
+ KotlinTokenId(tokenType.name, tokenType.name, tokenType.getId()),
+ lastElement.text, tokenType))
+ } else {
+ tokens.add(KotlinToken(
+ KotlinTokenId(TokenType.EOF.name, TokenType.EOF.name, TokenType.EOF.getId()),
+ "", TokenType.EOF))
+ break
+ }
+ }
+ }
+
+ fun getNextToken(): KotlinToken<KotlinTokenId>? {
+ if (input == null) return null
+ return if (tokens.isNotEmpty()) {
+ val ktToken = tokens.first()
+ tokens.removeAt(0)
+ var tokenLength = ktToken.length()
+ while (tokenLength > 0) {
+ input.read()
+ tokenLength--
+ }
+ ktToken
+ } else {
+ input.read()
+ KotlinToken(KotlinTokenId(TokenType.EOF.name, TokenType.EOF.name, TokenType.EOF.getId()),
+ "", TokenType.EOF)
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/KotlinTokensFactory.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/KotlinTokensFactory.kt
new file mode 100644
index 0000000..4a90852
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/KotlinTokensFactory.kt
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter
+
+import org.jetbrains.kotlin.lexer.KtTokens
+import com.intellij.psi.impl.source.tree.LeafPsiElement
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
+
+class KotlinTokensFactory {
+
+ fun getToken(leafElement: PsiElement): TokenType {
+ if (leafElement !is LeafPsiElement) return TokenType.UNDEFINED
+
+ val elementType = leafElement.elementType
+ return when (elementType) {
+ in KtTokens.KEYWORDS, in KtTokens.SOFT_KEYWORDS, in KtTokens.MODIFIER_KEYWORDS -> TokenType.KEYWORD
+ in KtTokens.STRINGS, KtTokens.OPEN_QUOTE, KtTokens.CLOSING_QUOTE -> TokenType.STRING
+ KtTokens.IDENTIFIER -> TokenType.IDENTIFIER
+ in KtTokens.WHITESPACES -> TokenType.WHITESPACE
+ KtTokens.EOL_COMMENT -> TokenType.SINGLE_LINE_COMMENT
+ in KtTokens.COMMENTS, in KDocTokens.KDOC_HIGHLIGHT_TOKENS -> TokenType.MULTI_LINE_COMMENT
+ KDocTokens.TAG_NAME -> TokenType.KDOC_LINK
+ else -> TokenType.UNDEFINED
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/TokenType.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/TokenType.kt
new file mode 100644
index 0000000..0954c69
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/TokenType.kt
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter
+
+enum class TokenType {
+ KEYWORD, IDENTIFIER, STRING, SINGLE_LINE_COMMENT,
+ MULTI_LINE_COMMENT, KDOC_TAG_NAME, WHITESPACE,
+ ANNOTATION, KDOC_LINK, UNDEFINED, EOF;
+
+ fun getId() = when(this) {
+ KEYWORD -> 0
+ IDENTIFIER -> 1
+ STRING -> 2
+ SINGLE_LINE_COMMENT -> 3
+ MULTI_LINE_COMMENT -> 4
+ KDOC_TAG_NAME -> 5
+ WHITESPACE -> 6
+ ANNOTATION -> 8
+ KDOC_LINK -> 9
+ else -> 7
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinLexerProxy.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinLexerProxy.kt
new file mode 100644
index 0000000..b4250bf
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinLexerProxy.kt
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.netbeans
+
+import org.jetbrains.kotlin.language.KotlinLanguageHierarchy
+import org.jetbrains.kotlin.highlighter.KotlinTokenScanner
+import org.netbeans.api.lexer.Token
+import org.netbeans.spi.lexer.Lexer
+import org.netbeans.spi.lexer.LexerInput
+import org.netbeans.spi.lexer.LexerRestartInfo
+
+class KotlinLexerProxy(private val info: LexerRestartInfo<KotlinTokenId>) : Lexer<KotlinTokenId> {
+
+ private val kotlinTokenScanner: KotlinTokenScanner by lazy { KotlinTokenScanner(input) }
+ private val input: LexerInput = info.input()
+
+ override fun nextToken(): Token<KotlinTokenId>? {
+ val token = kotlinTokenScanner.getNextToken()
+
+ if (input.readLength() < 1) return null
+
+ return if (token == null) {
+ info.tokenFactory().createToken(KotlinLanguageHierarchy.getToken(7))
+ } else {
+ info.tokenFactory().createToken(KotlinLanguageHierarchy.getToken(token.id().ordinal()))
+ }
+ }
+
+ override fun state() = null
+ override fun release() {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinToken.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinToken.kt
new file mode 100644
index 0000000..5b23392
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinToken.kt
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.netbeans
+
+import org.jetbrains.kotlin.highlighter.TokenType
+import org.netbeans.api.lexer.TokenId
+
+class KotlinToken<out T : TokenId>(val value: T, val text: String, val type: TokenType) {
+
+ fun id() = value as KotlinTokenId
+ fun text() = text
+ fun length() = text.length
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinTokenId.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinTokenId.kt
new file mode 100644
index 0000000..138f6df
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/netbeans/KotlinTokenId.kt
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.netbeans
+
+import org.jetbrains.kotlin.language.KotlinLanguageHierarchy
+import org.netbeans.api.lexer.Language
+import org.netbeans.api.lexer.TokenId
+
+class KotlinTokenId(private val tokenName: String, private val category: String, val id: Int) : TokenId {
+
+ companion object {
+ fun getLanguage(): Language<KotlinTokenId> = KotlinLanguageHierarchy().language()
+ }
+
+ override fun name() = tokenName
+ override fun ordinal() = id
+ override fun primaryCategory() = category
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/KotlinOccurrencesFinder.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/KotlinOccurrencesFinder.kt
new file mode 100644
index 0000000..91887f0
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/KotlinOccurrencesFinder.kt
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.occurrences
+
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.navigation.references.resolveToSourceDeclaration
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.isScanning
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.language.Priorities
+import org.netbeans.modules.csl.api.ColoringAttributes
+import org.netbeans.modules.csl.api.OccurrencesFinder
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.parsing.spi.Scheduler
+import org.netbeans.modules.parsing.spi.SchedulerEvent
+
+class KotlinOccurrencesFinder : OccurrencesFinder<KotlinParserResult>() {
+
+ private var caretPosition = 0
+ private var cancel = false
+ private val highlighting = hashMapOf<OffsetRange, ColoringAttributes>()
+
+ override fun run(result: KotlinParserResult?, event: SchedulerEvent?) {
+ cancel = false
+ highlighting.clear()
+ if (result == null) return
+
+ if (result.project.isScanning()) return
+
+ val ktFile = result.ktFile
+
+ val psiElement = ktFile.findElementAt(caretPosition)
+ val ktElement = PsiTreeUtil.getNonStrictParentOfType(psiElement, KtElement::class.java) ?: return
+ findOccurrences(ktElement, ktFile)
+ }
+
+ override fun getSchedulerClass(): Class<out Scheduler> = Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER
+
+ override fun getPriority() = Priorities.OCCURRENCES_FINDER_PRIORITY
+
+ override fun getOccurrences() = highlighting
+
+ override fun cancel() {
+ cancel = true
+ }
+
+ override fun setCaretPosition(position: Int) {
+ caretPosition = position
+ }
+
+ private fun findOccurrences(ktElement : KtElement, ktFile: KtFile) {
+ val sourceElements = ktElement.resolveToSourceDeclaration()
+ if (sourceElements.isEmpty()) return
+
+ val searchingElements = getSearchingElements(sourceElements)
+ val ranges = search(searchingElements, ktFile)
+ ranges.forEach { highlighting.put(it, ColoringAttributes.MARK_OCCURRENCES) }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/occurrencesUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/occurrencesUtils.kt
new file mode 100644
index 0000000..ee0e8d1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/occurrencesUtils.kt
@@ -0,0 +1,90 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.highlighter.occurrences
+
+import com.intellij.psi.PsiElement
+import kotlin.Pair
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.navigation.references.*
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.KtNamedDeclaration
+import org.jetbrains.kotlin.psi.KtReferenceExpression
+import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
+import org.netbeans.modules.csl.api.OffsetRange
+
+private fun getLengthOfIdentifier(ktElement: KtElement?) = when (ktElement) {
+ is KtNamedDeclaration -> {
+ val nameIdentifier = ktElement.nameIdentifier
+ if (nameIdentifier == null) null else {
+ Pair(nameIdentifier.textRange.startOffset, nameIdentifier.textRange.endOffset)
+ }
+ }
+ is KtReferenceExpression -> Pair(ktElement.textRange.startOffset, ktElement.textRange.endOffset)
+ else -> null
+}
+
+fun search(searchElement: KtElement, ktFile: KtFile) = searchTextOccurrences(ktFile, searchElement)
+ .mapNotNull { getLengthOfIdentifier(it) }
+ .map { OffsetRange(it.first, it.second) }
+
+fun search(searchingElements: List<SourceElement>, ktFile: KtFile): List<OffsetRange> {
+ val searchElements = getKotlinElements(searchingElements)
+ if (searchElements.isEmpty()) return emptyList()
+
+ val searchElement = searchElements.first()
+ val occurrences = searchTextOccurrences(ktFile, searchElement)
+
+ return occurrences.mapNotNull { getLengthOfIdentifier(it)?.let { OffsetRange(it.first, it.second) } }
+}
+
+fun getKotlinElements(sourceElements: List<SourceElement>) = sourceElements
+ .filterIsInstance(KotlinSourceElement::class.java)
+ .map { it.psi }
+
+fun searchTextOccurrences(ktFile: KtFile, sourceElement: KtElement): List<KtElement> {
+ val elementName = sourceElement.name ?: return emptyList()
+ val elements: Collection<KtElement> = getAllOccurrencesInFile(ktFile, elementName)
+ .mapNotNull { it.getNonStrictParentOfType(KtElement::class.java) }
+
+ return elements.filter { it.filterBeforeResolve() }
+ .filter { it.resolveToSourceDeclaration().filterAfterResolve(sourceElement) }
+}
+
+private fun getAllOccurrencesInFile(ktFile: KtFile, text: String): List<PsiElement> {
+ val elements = arrayListOf<PsiElement>()
+ val source = ktFile.text
+ var start = 0
+ while (true) {
+ val index = source.indexOf(text, start)
+ if (index == -1) break
+
+ val psiElement = ktFile.findElementAt(index)
+ if (psiElement != null) elements.add(psiElement)
+
+ start = index + text.length
+ }
+ return elements
+}
+
+fun getSearchingElements(sourceElements: List<SourceElement>): List<SourceElement> {
+ val classOrObjects = sourceElements.getContainingClassOrObjectForConstructor()
+ return if (classOrObjects.isEmpty()) sourceElements else classOrObjects
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/searchFilters.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/searchFilters.kt
new file mode 100644
index 0000000..2e741d3
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/occurrences/searchFilters.kt
@@ -0,0 +1,42 @@
+package org.jetbrains.kotlin.highlighter.occurrences
+
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtReferenceExpression
+import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.jetbrains.kotlin.psi.psiUtil.isImportDirectiveExpression
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.psi.KtNamedDeclaration
+
+interface SearchFilter {
+ fun isApplicable(jetElement: KtElement): Boolean
+}
+
+interface SearchFilterAfterResolve {
+ fun isApplicable(sourceElement: KtElement, originElement: KtElement): Boolean
+
+ fun isApplicable(sourceElements: List<SourceElement>, originElement: KtElement): Boolean {
+ val kotlinElements = getKotlinElements(sourceElements)
+ return kotlinElements.any { isApplicable(it, originElement) }
+ }
+}
+
+fun KtElement.filterBeforeResolve() = beforeResolveFilters().none { !it.isApplicable(this) }
+
+fun List<SourceElement>.filterAfterResolve(origin: KtElement) = afterResolveFilters().none { !it.isApplicable(this, origin) }
+
+private fun beforeResolveFilters() = listOf(NonImportFilter(), ReferenceFilter())
+
+private fun afterResolveFilters() = listOf(ResolvedReferenceFilter())
+
+class ReferenceFilter : SearchFilter {
+ override fun isApplicable(jetElement: KtElement): Boolean = jetElement is KtReferenceExpression || jetElement is KtNamedDeclaration
+}
+
+class NonImportFilter : SearchFilter {
+ override fun isApplicable(jetElement: KtElement): Boolean =
+ jetElement !is KtSimpleNameExpression || !jetElement.isImportDirectiveExpression()
+}
+
+class ResolvedReferenceFilter : SearchFilterAfterResolve {
+ override fun isApplicable(sourceElement: KtElement, originElement: KtElement) = sourceElement == originElement
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinHighlightingAttributes.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinHighlightingAttributes.kt
new file mode 100644
index 0000000..6164db7
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinHighlightingAttributes.kt
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.semanticanalyzer
+
+import org.netbeans.modules.csl.api.ColoringAttributes
+
+class KotlinHighlightingAttributes private constructor() {
+ lateinit var styleKey: Set<ColoringAttributes>
+
+ companion object {
+ fun withAttributes(changeAttributes: KotlinHighlightingAttributes.() -> Unit): KotlinHighlightingAttributes {
+ val attributes = KotlinHighlightingAttributes()
+ attributes.changeAttributes()
+ return attributes
+ }
+
+ val LOCAL_FINAL_VARIABLE = withAttributes { styleKey = setOf(ColoringAttributes.LOCAL_VARIABLE) }
+ val LOCAL_VARIABLE = withAttributes { styleKey = setOf(ColoringAttributes.LOCAL_VARIABLE,
+ ColoringAttributes.CUSTOM2) }
+ val PARAMETER_VARIABLE = withAttributes { styleKey = setOf(ColoringAttributes.PARAMETER) }
+ val FIELD = withAttributes { styleKey = setOf(ColoringAttributes.FIELD,
+ ColoringAttributes.CUSTOM2,
+ /*bold*/ColoringAttributes.ENUM) }
+ val FINAL_FIELD = withAttributes { styleKey = setOf(ColoringAttributes.FIELD,
+ /*bold*/ColoringAttributes.ENUM) }
+ val STATIC_FIELD = withAttributes { styleKey = setOf(ColoringAttributes.FIELD,
+ ColoringAttributes.STATIC,
+ ColoringAttributes.CUSTOM2,
+ /*bold*/ColoringAttributes.ENUM) }
+ val STATIC_FINAL_FIELD = withAttributes { styleKey = setOf(ColoringAttributes.FIELD,
+ ColoringAttributes.STATIC,
+ /*bold*/ColoringAttributes.ENUM) }
+ val TYPE_PARAMETER = withAttributes { styleKey = setOf(ColoringAttributes.TYPE_PARAMETER_USE) }
+ val ANNOTATION = withAttributes { styleKey = setOf(ColoringAttributes.ANNOTATION_TYPE) }
+ val INTERFACE = withAttributes { styleKey = setOf(ColoringAttributes.INTERFACE) }
+ val CLASS = withAttributes { styleKey = setOf(ColoringAttributes.CLASS) }
+ val FUNCTION_DECLARATION = withAttributes { styleKey = setOf(ColoringAttributes.DECLARATION) }
+ val SMART_CAST = withAttributes { styleKey = setOf(ColoringAttributes.CUSTOM1) }
+ val DEPRECATED = withAttributes { styleKey = setOf(ColoringAttributes.DEPRECATED) }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinSemanticAnalyzer.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinSemanticAnalyzer.kt
new file mode 100644
index 0000000..3c10fe2
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinSemanticAnalyzer.kt
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.semanticanalyzer
+
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.isScanning
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.language.Priorities
+import org.netbeans.modules.csl.api.ColoringAttributes
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.csl.api.SemanticAnalyzer
+import org.netbeans.modules.parsing.spi.Scheduler
+import org.netbeans.modules.parsing.spi.SchedulerEvent
+
+class KotlinSemanticAnalyzer : SemanticAnalyzer<KotlinParserResult>() {
+
+ private var cancel = false
+ private val highlighting = hashMapOf<OffsetRange, Set<ColoringAttributes>>()
+
+ private fun highlightDeprecatedElements(bindingContext: BindingContext, ktFile: KtFile) =
+ bindingContext.diagnostics
+ .filter { it.factory == Errors.DEPRECATION }
+ .filter { it.psiFile == ktFile }
+ .map { OffsetRange(it.textRanges.first().startOffset,
+ it.textRanges.first().endOffset) }
+ .forEach { highlighting.put(it, KotlinHighlightingAttributes.DEPRECATED.styleKey) }
+
+ override fun getPriority() = Priorities.SEMANTIC_ANALYZER_PRIORITY
+
+ override fun getHighlights() = highlighting
+
+ override fun run(result: KotlinParserResult?, event: SchedulerEvent?) {
+ highlighting.clear()
+ cancel = false
+
+ if (result == null || result.project.isScanning()) return
+
+ val analysisResult = result.analysisResult?.analysisResult ?: return
+
+ highlight(analysisResult, result.ktFile)
+ }
+
+ fun highlight(analysisResult: AnalysisResult, ktFile: KtFile) {
+ val highlightingVisitor = KotlinSemanticHighlightingVisitor(ktFile, analysisResult)
+ highlighting.putAll(highlightingVisitor.computeHighlightingRanges())
+
+ highlightDeprecatedElements(analysisResult.bindingContext, ktFile)
+ }
+
+ override fun cancel() {
+ cancel = true
+ }
+
+ override fun getSchedulerClass(): Class<out Scheduler> = Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinSemanticHighlightingVisitor.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinSemanticHighlightingVisitor.kt
new file mode 100644
index 0000000..fd07923
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/highlighter/semanticanalyzer/KotlinSemanticHighlightingVisitor.kt
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.highlighter.semanticanalyzer
+
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.renderer.DescriptorRenderer
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.netbeans.modules.csl.api.ColoringAttributes
+import org.netbeans.modules.csl.api.OffsetRange
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.descriptors.ClassKind
+
+class KotlinSemanticHighlightingVisitor(val ktFile: KtFile,
+ val result: AnalysisResult) : KtVisitorVoid() {
+
+ private lateinit var bindingContext: BindingContext
+ private val positions = hashMapOf<OffsetRange, Set<ColoringAttributes>>()
+
+ fun computeHighlightingRanges(): Map<OffsetRange, Set<ColoringAttributes>> {
+ positions.clear()
+ bindingContext = result.bindingContext
+ ktFile.acceptChildren(this)
+
+ return positions
+ }
+
+ private fun highlight(styleAttributes: KotlinHighlightingAttributes, range: TextRange) {
+ val offsetRange = OffsetRange(range.startOffset, range.endOffset)
+ positions.put(offsetRange, styleAttributes.styleKey)
+ }
+
+ private fun highlight(styleAttributes: Set<ColoringAttributes>, range: TextRange) {
+ val offsetRange = OffsetRange(range.startOffset, range.endOffset)
+ positions.put(offsetRange, styleAttributes)
+ }
+
+ override fun visitElement(element: PsiElement) = element.acceptChildren(this)
+
+ override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
+ val parentExpression = expression.parent
+ if (parentExpression is KtThisExpression || parentExpression is KtSuperExpression) return
+
+ val target = bindingContext[BindingContext.REFERENCE_TARGET, expression]?.let {
+ (it as? ConstructorDescriptor)?.containingDeclaration ?: it
+ } ?: return
+
+ val smartCast = bindingContext.get(BindingContext.SMARTCAST, expression)
+ val typeName = smartCast?.defaultType?.let { DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) }
+
+ when (target) {
+ is TypeParameterDescriptor -> highlightTypeParameter(expression)
+ is ClassDescriptor -> highlightClassDescriptor(expression, target)
+ is PropertyDescriptor -> highlightProperty(expression, target, typeName)
+ is VariableDescriptor -> highlightVariable(expression, target, typeName)
+ }
+ super.visitSimpleNameExpression(expression)
+ }
+
+ override fun visitTypeParameter(parameter: KtTypeParameter) {
+ val identifier = parameter.nameIdentifier
+ if (identifier != null) highlightTypeParameter(identifier)
+
+ super.visitTypeParameter(parameter)
+ }
+
+ override fun visitClassOrObject(classOrObject: KtClassOrObject) {
+ val identifier = classOrObject.nameIdentifier
+ if (identifier == null) {
+ classOrObject.acceptChildren(this)
+ return
+ }
+ val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject)
+ if (classDescriptor != null) {
+ highlightClassDescriptor(identifier, classDescriptor)
+ }
+
+ super.visitClassOrObject(classOrObject)
+ }
+
+ override fun visitProperty(property: KtProperty) {
+ val nameIdentifier = property.nameIdentifier ?: return
+ try {
+ val propertyDescriptor = bindingContext[BindingContext.VARIABLE, property]
+ if (propertyDescriptor is PropertyDescriptor) {
+ highlightProperty(nameIdentifier, propertyDescriptor)
+ } else visitVariableDeclaration(property)
+ } catch (ex: IllegalArgumentException) {
+ return
+ }
+ super.visitProperty(property)
+ }
+
+ override fun visitParameter(parameter: KtParameter) {
+ val nameIdentifier = parameter.nameIdentifier ?: return
+ val propertyDescriptor = bindingContext[BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter]
+ if (propertyDescriptor is PropertyDescriptor) {
+ highlightProperty(nameIdentifier, propertyDescriptor)
+ } else {
+ visitVariableDeclaration(parameter)
+ }
+
+ super.visitParameter(parameter)
+ }
+
+ override fun visitNamedFunction(function: KtNamedFunction) {
+ val nameIdentifier = function.nameIdentifier
+ if (nameIdentifier != null) {
+ highlight(KotlinHighlightingAttributes.FUNCTION_DECLARATION, nameIdentifier.textRange)
+ }
+
+ super.visitNamedFunction(function)
+ }
+
+ private fun visitVariableDeclaration(declaration: KtNamedDeclaration) {
+ val declarationDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
+ val nameIdentifier = declaration.nameIdentifier
+ if (nameIdentifier != null && declarationDescriptor != null) {
+ highlightVariable(nameIdentifier, declarationDescriptor)
+ }
+ }
+
+ private fun highlightTypeParameter(element: PsiElement) =
+ highlight(KotlinHighlightingAttributes.TYPE_PARAMETER, element.textRange)
+
+ private fun highlightAnnotation(expression: PsiElement) {
+ var range = expression.textRange
+ val annotationEntry = PsiTreeUtil.getParentOfType<KtAnnotationEntry>(expression, KtAnnotationEntry::class.java,
+ false, KtValueArgumentList::class.java)
+
+ if (annotationEntry != null) {
+ val atSymbol = annotationEntry.atSymbol
+ if (atSymbol != null) range = TextRange(atSymbol.textRange.startOffset, expression.textRange.endOffset)
+ }
+ highlight(KotlinHighlightingAttributes.ANNOTATION, range)
+ }
+
+ private fun highlightClassDescriptor(element: PsiElement, target: ClassDescriptor) = when (target.kind) {
+ ClassKind.INTERFACE -> highlight(KotlinHighlightingAttributes.INTERFACE, element.textRange)
+ ClassKind.ANNOTATION_CLASS -> highlightAnnotation(element)
+ ClassKind.ENUM_ENTRY -> highlight(KotlinHighlightingAttributes.STATIC_FINAL_FIELD, element.textRange)
+ ClassKind.CLASS, ClassKind.OBJECT -> highlight(KotlinHighlightingAttributes.CLASS, element.textRange)
+ else -> { }
+ }
+
+ private fun highlightProperty(element: PsiElement, descriptor: PropertyDescriptor, typeName: String? = null) {
+ val range = element.textRange
+ val mutable = descriptor.isVar
+ val attributes = if (DescriptorUtils.isStaticDeclaration(descriptor)) {
+ if (mutable) KotlinHighlightingAttributes.STATIC_FIELD else KotlinHighlightingAttributes.STATIC_FINAL_FIELD
+ } else {
+ if (mutable) KotlinHighlightingAttributes.FIELD else KotlinHighlightingAttributes.FINAL_FIELD
+
+ }
+ val styleAttributes = attributes.styleKey.toMutableSet()
+ if (typeName != null) styleAttributes.addAll(KotlinHighlightingAttributes.SMART_CAST.styleKey)
+
+ highlight(styleAttributes, range)
+ }
+
+ private fun highlightVariable(element: PsiElement, descriptor: DeclarationDescriptor, typeName: String? = null) {
+ if (descriptor !is VariableDescriptor) return
+
+ val attributes = when (descriptor) {
+ is LocalVariableDescriptor -> {
+ if (descriptor.isVar) {
+ KotlinHighlightingAttributes.LOCAL_VARIABLE
+ } else {
+ KotlinHighlightingAttributes.LOCAL_FINAL_VARIABLE
+ }
+ }
+
+ is ValueParameterDescriptor -> KotlinHighlightingAttributes.PARAMETER_VARIABLE
+
+ else -> KotlinHighlightingAttributes.LOCAL_VARIABLE
+ }
+ val styleAttributes = attributes.styleKey.toMutableSet()
+ if (typeName != null) styleAttributes.addAll(KotlinHighlightingAttributes.SMART_CAST.styleKey)
+
+ highlight(styleAttributes, element.textRange)
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinHintsComputer.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinHintsComputer.kt
new file mode 100644
index 0000000..4bfc10a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinHintsComputer.kt
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints
+
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.hints.intentions.*
+import org.jetbrains.kotlin.psi.*
+import org.netbeans.modules.csl.api.Hint
+
+class KotlinHintsComputer(val parserResult: KotlinParserResult) : KtVisitor<Unit, Any?>() {
+
+ val hints = arrayListOf<Hint>()
+
+ override fun visitKtFile(ktFile: KtFile, data: Any?) {
+ ktFile.acceptChildren(this)
+ }
+
+ override fun visitKtElement(element: KtElement, data: Any?) {
+ hints.addAll(element.inspections())
+
+ element.acceptChildren(this)
+ }
+
+ override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Any?) {
+ getSmartCastHover(expression, parserResult)?.let { hints.add(it) }
+ }
+
+ private fun KtElement.inspections() = listOf(
+ RemoveEmptyPrimaryConstructorInspection(parserResult, this),
+ RemoveEmptyClassBodyInspection(parserResult, this),
+ ConvertToStringTemplateInspection(parserResult, this),
+ ConvertTryFinallyToUseCallInspection(parserResult, this),
+ RemoveEmptySecondaryConstructorInspection(parserResult, this),
+ ReplaceSizeCheckWithIsNotEmptyInspection(parserResult, this)
+ )
+ .filter(Inspection::isApplicable)
+ .map { it.hint(parserResult.snapshot.source.fileObject) }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinHintsProvider.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinHintsProvider.kt
new file mode 100644
index 0000000..45cc955
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinHintsProvider.kt
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints
+
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import javax.swing.text.StyledDocument
+import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
+import org.jetbrains.kotlin.hints.fixes.*
+import org.jetbrains.kotlin.hints.intentions.*
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.netbeans.modules.csl.api.*
+import org.openide.text.NbDocument
+import org.netbeans.modules.csl.api.HintsProvider.HintsManager
+import org.netbeans.modules.csl.api.HintSeverity
+
+class KotlinHintsProvider : HintsProvider {
+
+ companion object {
+
+ private fun listOfIntentions(parserResult: KotlinParserResult,
+ psi: PsiElement) = parserResult.let {
+ Pair(it.snapshot.source.getDocument(false), it.analysisResult?.analysisResult)
+ }.let {
+ listOf(
+ RemoveExplicitTypeIntention(it.first, it.second, psi),
+ SpecifyTypeIntention(it.first, it.second, psi),
+ ConvertToBlockBodyIntention(it.first, it.second, psi),
+ ConvertToExpressionBodyIntention(it.first, it.second, psi),
+ ChangeReturnTypeIntention(it.first, it.second, psi),
+ ConvertTryFinallyToUseCallIntention(it.first, it.second, psi),
+ ConvertForEachToForLoopIntention(it.first, it.second, psi),
+ ConvertEnumToSealedClassIntention(it.first, it.second, psi),
+ AddValToConstructorParameterIntention(it.first, it.second, psi),
+ ConvertPropertyInitializerToGetterIntention(it.first, it.second, psi),
+ ConvertToConcatenatedStringIntention(it.first, it.second, psi),
+ ConvertToStringTemplateIntention(it.first, it.second, psi),
+ ConvertTwoComparisonsToRangeCheckIntention(it.first, it.second, psi),
+ MergeIfsIntention(it.first, it.second, psi),
+ RemoveBracesIntention(it.first, it.second, psi),
+ SplitIfIntention(it.first, it.second, psi),
+ ToInfixIntention(it.first, it.second, psi),
+ RemoveEmptyClassBodyIntention(it.first, it.second, psi),
+ RemoveEmptyParenthesesFromLambdaCallIntention(it.first, it.second, psi),
+ RemoveEmptyPrimaryConstructorIntention(it.first, it.second, psi),
+ RemoveEmptySecondaryConstructorIntention(it.first, it.second, psi),
+ ReplaceSizeCheckWithIsNotEmptyIntention(it.first, it.second, psi)
+ ).filter { it.isApplicable(psi.textRange.startOffset) }
+ }
+
+ private fun KotlinError.listOfQuickFixes(parserResult: KotlinParserResult) = listOf(
+ RemoveUselessElvisFix(this, parserResult),
+ ImplementMembersFix(this, parserResult),
+ AutoImportFix(this, parserResult),
+ RemoveUselessCastFix(this, parserResult),
+ RemoveUnnecessarySafeCallFix(this, parserResult)
+ ).filter(KotlinQuickFix::isApplicable)
+
+ private val RuleContext.quickFixes
+ get() = parserResult.diagnostics
+ .filterIsInstance(KotlinError::class.java)
+ .flatMap { it.listOfQuickFixes(parserResult as KotlinParserResult) }
+ .map(KotlinQuickFix::createHint)
+
+ }
+
+ override fun computeSuggestions(hintsManager: HintsManager, ruleContext: RuleContext,
+ hints: MutableList<Hint>, offset: Int) {
+ val parserResult = ruleContext.parserResult as KotlinParserResult
+ val doc = ruleContext.doc as StyledDocument
+
+ val lineNumber = NbDocument.findLineNumber(doc, offset)
+ val lastLine = NbDocument.findLineNumber(doc, doc.length)
+
+ if (lineNumber == lastLine) return
+
+ val lineStartOffset = NbDocument.findLineOffset(doc, lineNumber)
+ val lineEndOffset = NbDocument.findLineOffset(doc, lineNumber + 1)
+
+ val intentions = parserResult.ktFile.elementsInRange(TextRange(lineStartOffset, lineEndOffset))
+ .toMutableList()
+ .apply {
+ val elem = parserResult.ktFile.findElementAt(offset)
+ if (elem != null) {
+ add(elem)
+ }
+ }
+ .map { psi ->
+ listOfIntentions(parserResult, psi)
+ .map {
+ Hint(KotlinRule(HintSeverity.CURRENT_LINE_WARNING),
+ it.description,
+ parserResult.snapshot.source.fileObject,
+ OffsetRange(offset, offset),
+ listOf(it),
+ 20
+ )
+ }
+ }
+
+ hints.addAll(
+ intentions.flatMap { it }
+ .distinctBy { it.description }
+ )
+
+ }
+
+ override fun computeHints(hintsManager: HintsManager, ruleContext: RuleContext, hints: MutableList<Hint>) {
+ val parserResult = ruleContext.parserResult as KotlinParserResult
+ val ktFile = parserResult.ktFile
+ val hintsComputer = KotlinHintsComputer(parserResult)
+ val unusedComputer = UnusedImportsComputer(parserResult)
+
+ ktFile.accept(hintsComputer)
+
+ with(hints) {
+ addAll(ruleContext.quickFixes)
+ addAll(hintsComputer.hints)
+ addAll(unusedComputer.getUnusedImports())
+ }
+ }
+
+ override fun computeSelectionHints(hintsManager: HintsManager, ruleContext: RuleContext,
+ list: List<Hint>, i: Int, i2: Int) {
+ }
+
+ override fun cancel() {}
+
+ override fun getBuiltinRules() = emptyList<Rule>()
+
+ override fun createRuleContext() = KotlinRuleContext()
+
+ override fun computeErrors(hintsManager: HintsManager, ruleContext: RuleContext,
+ list: List<Hint>, errors: MutableList<Error>) {
+ errors.addAll(ruleContext.parserResult.diagnostics)
+ }
+
+}
+
+fun Document.atomicChange(change: Document.() -> Unit) = NbDocument.runAtomicAsUser(this as StyledDocument, { change() })
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinRule.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinRule.kt
new file mode 100644
index 0000000..959c0fa
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/KotlinRule.kt
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints
+
+import org.netbeans.modules.csl.api.HintSeverity
+import org.netbeans.modules.csl.api.Rule
+import org.netbeans.modules.csl.api.RuleContext
+
+class KotlinRule(private val severity: HintSeverity) : Rule {
+
+ override fun appliesTo(context: RuleContext) = context is KotlinRuleContext
+ override fun getDisplayName() = ""
+ override fun showInTasklist() = false
+ override fun getDefaultSeverity() = severity
+}
+
+class KotlinRuleContext : RuleContext()
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/UnusedImportsComputer.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/UnusedImportsComputer.kt
new file mode 100644
index 0000000..c218098
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/UnusedImportsComputer.kt
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints
+
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.language.Priorities
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.descriptors.*
+import org.netbeans.modules.csl.api.Hint
+import org.netbeans.modules.csl.api.HintFix
+import org.netbeans.modules.csl.api.HintSeverity
+import org.netbeans.modules.csl.api.OffsetRange
+
+class UnusedImportsComputer(private val parserResult: KotlinParserResult) : KtVisitor<Unit, Any?>() {
+
+ private val ktFile = parserResult.ktFile
+ private val context = parserResult.analysisResult!!.analysisResult.bindingContext
+ private val usedClasses = hashSetOf<ClassDescriptor>()
+
+ fun getUnusedImports(): List<Hint> {
+ ktFile.accept(this)
+ val unusedImports = hashSetOf<KtImportDirective>()
+
+ ktFile.importDirectives
+ .forEach {
+ val ref = PsiTreeUtil.findChildrenOfType(it, KtReferenceExpression::class.java).lastOrNull()
+ val target = context[BindingContext.REFERENCE_TARGET, ref]
+ if (target is ClassDescriptor && target !in usedClasses) unusedImports.add(it)
+ }
+
+ return unusedImports.map {
+ Hint(KotlinRule(HintSeverity.WARNING),
+ "Unused import: ${it.importedFqName}",
+ parserResult.snapshot.source.fileObject,
+ OffsetRange(it.textRange.startOffset, it.textRange.endOffset),
+ listOf(UnusedHintFix(parserResult, it)),
+ Priorities.HINT_PRIORITY)
+ }
+ }
+
+ override fun visitKtFile(ktFile: KtFile, data: Any?) {
+ ktFile.acceptChildren(this)
+ }
+
+ override fun visitKtElement(element: KtElement, data: Any?) {
+ element.acceptChildren(this)
+ }
+
+ override fun visitImportDirective(importDirective: KtImportDirective, data: Any?) {}
+
+ override fun visitReferenceExpression(expression: KtReferenceExpression, data: Any?) {
+ val reference = context[BindingContext.REFERENCE_TARGET, expression]?.let {
+ if (it is ClassDescriptor && !it.isCompanionObject) it else it.containingDeclaration
+ }
+
+ if (reference is ClassDescriptor) usedClasses.add(reference)
+
+ expression.acceptChildren(this)
+ }
+
+}
+
+class UnusedHintFix(private val parserResult: KotlinParserResult,
+ private val importDirective: KtImportDirective) : HintFix {
+ override fun isSafe() = true
+
+ override fun isInteractive() = false
+
+ override fun getDescription() = "Remove unused import"
+
+ override fun implement() {
+ val doc = parserResult.snapshot.source.getDocument(false)
+ val startOffset = importDirective.textRange.startOffset - 1
+ val length = importDirective.textRange.endOffset - startOffset
+ doc.remove(startOffset, length)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/AutoImportFix.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/AutoImportFix.kt
new file mode 100644
index 0000000..241a475
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/AutoImportFix.kt
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.fixes
+
+import javax.swing.text.Document
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.resolve.lang.java.findFQName
+import org.jetbrains.kotlin.search.PublicFunctionsVisitor
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.HintSeverity
+
+
+fun autoImport(fqName: String, doc: Document) {
+ val file = ProjectUtils.getFileObjectForDocument(doc) ?: return
+ val ktFile = ProjectUtils.getKtFile(doc.getText(0, doc.length), file) ?: return
+
+ insert(fqName, doc, ktFile)
+}
+
+private fun insert(fqName: String, doc: Document, ktFile: KtFile) {
+ val importDirectives = ktFile.importDirectives
+ val packageDirective = ktFile.packageDirective
+
+ if (importDirectives.isNotEmpty()) {
+ val offset = getOffsetToInsert(importDirectives, fqName)
+ if (offset != null) {
+ doc.insertString(offset,
+ "import $fqName\n", null)
+ } else {
+ doc.insertString(importDirectives.last().textRange.endOffset,
+ "\nimport $fqName", null)
+ }
+ } else if (packageDirective != null) {
+ doc.insertString(packageDirective.textOffset + packageDirective.textLength,
+ "\n\nimport $fqName", null)
+ } else {
+ doc.insertString(0, "import $fqName", null)
+ }
+}
+
+private fun getOffsetToInsert(importDirectives: List<KtImportDirective>, fqName: String): Int? {
+ importDirectives.filter { it.importedFqName != null }
+ .forEach {
+ if (it.importedFqName!!.asString() > fqName) {
+ return it.textRange.startOffset
+ }
+ }
+ return null
+}
+
+private fun Project.getPublicFunctions(name: String) = ProjectUtils.getSourceFiles(this)
+ .flatMap { ktFile ->
+ PublicFunctionsVisitor({ it == name }).let {
+ ktFile.acceptChildren(it)
+ it.publicFunctions
+ }
+ }
+
+class AutoImportFix(kotlinError: KotlinError,
+ parserResult: KotlinParserResult) : KotlinQuickFix(kotlinError, parserResult) {
+
+ private var fqName: String? = null
+ private val types by lazy { parserResult.project.findFQName(kotlinError.psi.text) }
+ private val suggestions by lazy { if (types.isNotEmpty()) types else parserResult.project.getPublicFunctions(kotlinError.psi.text) }
+
+ constructor(kotlinError: KotlinError,
+ parserResult: KotlinParserResult,
+ fqName: String) : this(kotlinError, parserResult) {
+ this.fqName = fqName
+ }
+
+ override val hintSeverity = HintSeverity.ERROR
+
+ override fun isApplicable() = when (kotlinError.diagnostic.factory) {
+ Errors.UNRESOLVED_REFERENCE -> suggestions.isNotEmpty()
+ else -> false
+ }
+
+ override fun createFixes() = suggestions.map { AutoImportFix(kotlinError, parserResult, it) }
+
+ override fun getDescription() = "Add import for $fqName"
+
+ override fun implement() {
+ val doc = parserResult.snapshot?.source?.getDocument(false) ?: ProjectUtils.getDocumentFromFileObject(parserResult.file)
+ val ktFile = parserResult.ktFile
+
+ insert(fqName!!, doc, ktFile)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/ImplementMembersFix.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/ImplementMembersFix.kt
new file mode 100644
index 0000000..163aeee
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/ImplementMembersFix.kt
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.fixes
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.renderer.*
+import org.jetbrains.kotlin.resolve.OverrideResolver
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.modules.csl.api.HintSeverity
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.resolve.BindingContextUtils
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.diagnostics.Errors
+import javax.swing.text.Document
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ImplementMembersFix(kotlinError: KotlinError,
+ parserResult: KotlinParserResult) : KotlinQuickFix(kotlinError, parserResult) {
+
+ override val hintSeverity = HintSeverity.ERROR
+
+ override fun isApplicable() = when (kotlinError.diagnostic.factory) {
+ Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED,
+ Errors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED -> true
+ else -> false
+ }
+
+ override fun createFixes() = listOf(this)
+
+ override fun getDescription() = "Implement members"
+
+ override fun implement() {
+ val doc = parserResult.snapshot?.source?.getDocument(false) ?: ProjectUtils.getDocumentFromFileObject(parserResult.file)
+
+ val classOrObject: KtClassOrObject = PsiTreeUtil.getParentOfType(kotlinError.psi, KtClassOrObject::class.java, false) ?: return
+
+ val missingImplementations = collectMethodsToGenerate(classOrObject)
+ if (missingImplementations.isEmpty()) return
+
+ doc.atomicChange {
+ generateMethods(this, classOrObject, missingImplementations)
+ format(this, classOrObject.textRange.startOffset)
+ }
+ }
+
+ private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
+ renderDefaultValues = false
+ modifiers = setOf(DescriptorRendererModifier.OVERRIDE)
+ withDefinedIn = false
+ classifierNamePolicy = ClassifierNamePolicy.SHORT
+ overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE
+ unitReturnType = false
+ typeNormalizer = IdeDescriptorRenderers.APPROXIMATE_FLEXIBLE_TYPES
+ }
+
+ private fun generateMethods(document: Document, classOrObject: KtClassOrObject, selectedElements: Set<CallableMemberDescriptor>) {
+ val body = classOrObject.getBody()
+ val psiFactory = KtPsiFactory(classOrObject.project)
+ if (body == null) {
+ val bodyText = "${psiFactory.createWhiteSpace().text}${psiFactory.createEmptyClassBody().text}"
+ insertAfter(classOrObject, bodyText, document)
+ } else {
+ removeWhitespaceAfterLBrace(body, document)
+ }
+
+ val insertOffset = findLBraceEndOffset(document, classOrObject.textRange.startOffset) ?: return
+
+ val generatedText = generateOverridingMembers(selectedElements, classOrObject, "\n")
+ .joinToString("\n", postfix = "\n") { it.node.text }
+
+ document.insertString(insertOffset, generatedText, null)
+ }
+
+ private fun insertAfter(psi: PsiElement, text: String, doc: Document) {
+ val end = psi.textRange.endOffset
+ doc.insertString(end, text, null)
+ }
+
+ private fun removeWhitespaceAfterLBrace(body: KtClassBody, document: Document) {
+ val lBrace = body.lBrace ?: return
+ val sibling = lBrace.nextSibling
+ val needNewLine = sibling.nextSibling is KtDeclaration
+ if (sibling is PsiWhiteSpace && !needNewLine) {
+ document.remove(sibling.textRange.startOffset, sibling.textLength)
+ }
+ }
+
+ private fun findLBraceEndOffset(document: Document, startIndex: Int): Int? {
+ val text = document.getText(0, document.length)
+
+ return (startIndex..text.lastIndex)
+ .firstOrNull { text[it] == '{' }
+ ?.let { it + 1 }
+ }
+
+ private fun DeclarationDescriptor.escapedName() = DescriptorRenderer.COMPACT.renderName(name)
+
+ private fun collectMethodsToGenerate(classOrObject: KtClassOrObject): Set<CallableMemberDescriptor> {
+ val descriptor = classOrObject.resolveToDescriptor()
+ if (descriptor is ClassDescriptor) {
+ return OverrideResolver.getMissingImplementations(descriptor)
+ }
+ return emptySet()
+ }
+
+ private fun KtElement.resolveToDescriptor(): DeclarationDescriptor {
+ val ktFile = containingKtFile
+ val analysisResult = KotlinAnalyzer.analyzeFile(parserResult.project, ktFile).analysisResult
+ return BindingContextUtils.getNotNull<PsiElement, DeclarationDescriptor>(
+ analysisResult.bindingContext,
+ BindingContext.DECLARATION_TO_DESCRIPTOR,
+ this,
+ "Descriptor wasn't found for declaration ${toString()}\n${getElementTextWithContext()}")
+ }
+
+ private fun generateUnsupportedOrSuperCall(descriptor: CallableMemberDescriptor): String {
+ val isAbstract = descriptor.modality == Modality.ABSTRACT
+ if (isAbstract) {
+ return "throw UnsupportedOperationException()"
+ } else {
+ val builder = StringBuilder()
+ builder.append("super.${descriptor.escapedName()}")
+
+ if (descriptor is FunctionDescriptor) {
+ val paramTexts = descriptor.valueParameters.map {
+ val renderedName = it.escapedName()
+ if (it.varargElementType != null) "*$renderedName" else renderedName
+ }
+ paramTexts.joinTo(builder, prefix = "(", postfix = ")")
+ }
+
+ return builder.toString()
+ }
+ }
+
+ private fun overrideProperty(classOrObject: KtClassOrObject,
+ descriptor: PropertyDescriptor,
+ lineDelimiter: String): KtElement {
+ val newDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
+ descriptor.kind, /* copyOverrides = */ true) as PropertyDescriptor
+ newDescriptor.overriddenDescriptors = listOf(descriptor)
+
+ val body = StringBuilder()
+ body.append("${lineDelimiter}get()")
+ body.append(" = ")
+ body.append(generateUnsupportedOrSuperCall(descriptor))
+ if (descriptor.isVar) {
+ body.append("${lineDelimiter}set(value) {\n}")
+ }
+ return KtPsiFactory(classOrObject.project).createProperty("${OVERRIDE_RENDERER.render(newDescriptor)}$body")
+ }
+
+ private fun overrideFunction(classOrObject: KtClassOrObject,
+ descriptor: FunctionDescriptor,
+ lineDelimiter: String): KtNamedFunction {
+ val newDescriptor: FunctionDescriptor = descriptor.copy(descriptor.containingDeclaration, Modality.OPEN, descriptor.visibility,
+ descriptor.kind, /* copyOverrides = */ true)
+ newDescriptor.overriddenDescriptors = listOf(descriptor)
+
+ val returnType = descriptor.returnType
+ val returnsNotUnit = returnType != null && !KotlinBuiltIns.isUnit(returnType)
+ val isAbstract = descriptor.modality == Modality.ABSTRACT
+
+ val delegation = generateUnsupportedOrSuperCall(descriptor)
+
+ val body = "{$lineDelimiter${if (returnsNotUnit && !isAbstract) "return " else ""}$delegation$lineDelimiter}"
+
+ return KtPsiFactory(classOrObject.project).createFunction("${OVERRIDE_RENDERER.render(newDescriptor)}$body")
+ }
+
+ private fun generateOverridingMembers(selectedElements: Set<CallableMemberDescriptor>,
+ classOrObject: KtClassOrObject,
+ lineDelimiter: String): List<KtElement> {
+ val overridingMembers = arrayListOf<KtElement>()
+ for (selectedElement in selectedElements) {
+ if (selectedElement is SimpleFunctionDescriptor) {
+ overridingMembers.add(overrideFunction(classOrObject, selectedElement, lineDelimiter))
+ } else if (selectedElement is PropertyDescriptor) {
+ overridingMembers.add(overrideProperty(classOrObject, selectedElement, lineDelimiter))
+ }
+ }
+ return overridingMembers
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/KotlinQuickFix.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/KotlinQuickFix.kt
new file mode 100644
index 0000000..9823572
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/KotlinQuickFix.kt
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.fixes
+
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.hints.KotlinRule
+import org.netbeans.modules.csl.api.Hint
+import org.netbeans.modules.csl.api.HintFix
+import org.netbeans.modules.csl.api.HintSeverity
+import org.netbeans.modules.csl.api.OffsetRange
+
+abstract class KotlinQuickFix(val kotlinError: KotlinError,
+ val parserResult: KotlinParserResult) : HintFix {
+
+ private val PRIORITY = 10
+
+ abstract val hintSeverity: HintSeverity
+
+ override fun isSafe() = true
+
+ override fun isInteractive() = false
+
+ abstract fun isApplicable(): Boolean
+
+ abstract fun createFixes(): List<KotlinQuickFix>
+
+ fun createHint() = Hint(
+ KotlinRule(hintSeverity),
+ description,
+ parserResult.snapshot.source.fileObject,
+ OffsetRange(kotlinError.startPosition, kotlinError.endPosition),
+ createFixes(),
+ PRIORITY
+ )
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUnnecessarySafeCallFix.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUnnecessarySafeCallFix.kt
new file mode 100644
index 0000000..fe66f80
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUnnecessarySafeCallFix.kt
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.fixes
+
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.modules.csl.api.HintSeverity
+
+class RemoveUnnecessarySafeCallFix(kotlinError: KotlinError,
+ parserResult: KotlinParserResult) : KotlinQuickFix(kotlinError, parserResult) {
+
+ override val hintSeverity = HintSeverity.WARNING
+
+ override fun isApplicable() = when (kotlinError.diagnostic.factory) {
+ Errors.UNNECESSARY_SAFE_CALL -> true
+ else -> false
+ }
+
+ override fun createFixes() = listOf(this)
+
+ override fun getDescription() = "Remove '?'"
+
+ override fun implement() {
+ val doc = parserResult.snapshot?.source?.getDocument(false) ?: ProjectUtils.getDocumentFromFileObject(parserResult.file)
+
+ doc.remove(kotlinError.startPosition, 1)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUselessCastFix.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUselessCastFix.kt
new file mode 100644
index 0000000..9e61afd
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUselessCastFix.kt
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.fixes
+
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.modules.csl.api.HintSeverity
+
+class RemoveUselessCastFix(kotlinError: KotlinError,
+ parserResult: KotlinParserResult) : KotlinQuickFix(kotlinError, parserResult) {
+
+ override val hintSeverity = HintSeverity.WARNING
+
+ override fun isApplicable() = when (kotlinError.diagnostic.factory) {
+ Errors.USELESS_CAST -> true
+ else -> false
+ }
+
+ override fun createFixes() = listOf(this)
+
+ override fun getDescription() = "Remove useless cast"
+
+ override fun implement() {
+ val doc = parserResult.snapshot?.source?.getDocument(false) ?: ProjectUtils.getDocumentFromFileObject(parserResult.file)
+
+ doc.remove(kotlinError.startPosition, kotlinError.endPosition - kotlinError.startPosition)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUselessElvisFix.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUselessElvisFix.kt
new file mode 100644
index 0000000..a7cacdd
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/fixes/RemoveUselessElvisFix.kt
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.fixes
+
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinError
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.modules.csl.api.HintSeverity
+
+class RemoveUselessElvisFix(kotlinError: KotlinError,
+ parserResult: KotlinParserResult) : KotlinQuickFix(kotlinError, parserResult) {
+
+ override val hintSeverity = HintSeverity.WARNING
+
+ override fun isApplicable() = when (kotlinError.diagnostic.factory) {
+ Errors.USELESS_ELVIS,
+ Errors.USELESS_ELVIS_ON_LAMBDA_EXPRESSION,
+ Errors.USELESS_ELVIS_RIGHT_IS_NULL -> true
+ else -> false
+ }
+
+ override fun createFixes() = listOf(this)
+
+ override fun getDescription() = "Remove useless elvis operator"
+
+ override fun implement() {
+ val doc = parserResult.snapshot?.source?.getDocument(false) ?: ProjectUtils.getDocumentFromFileObject(parserResult.file)
+
+ doc.remove(kotlinError.startPosition, kotlinError.endPosition - kotlinError.startPosition)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/AddValToConstructorParameterIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/AddValToConstructorParameterIntention.kt
new file mode 100644
index 0000000..7a2c06b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/AddValToConstructorParameterIntention.kt
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+
+class AddValToConstructorParameterIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var parameter: KtParameter? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ parameter = psi.getNonStrictParentOfType(KtParameter::class.java) ?: return false
+ val element = parameter ?: return false
+
+ if (!canInvoke(element)) return false
+ if (element.getNonStrictParentOfType(KtClass::class.java)?.isData() == true) return false
+
+ return element.nameIdentifier?.textRange != null
+ }
+
+ override fun getDescription() = "Add val to parameter '${parameter?.name ?: ""}'"
+
+ override fun implement() {
+ val element = parameter ?: return
+
+ val startOffset = element.textRange.startOffset
+
+ doc.insertString(startOffset, "val ", null)
+ }
+
+ private fun canInvoke(element: KtParameter): Boolean =
+ element.valOrVarKeyword == null && (element.parent as? KtParameterList)?.parent is KtPrimaryConstructor
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ApplicableIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ApplicableIntention.kt
new file mode 100644
index 0000000..721d1be
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ApplicableIntention.kt
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.language.Priorities
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.hints.KotlinRule
+import org.netbeans.modules.csl.api.*
+import org.openide.filesystems.FileObject
+
+abstract class ApplicableIntention(val doc: Document,
+ val analysisResult: AnalysisResult?,
+ val psi: PsiElement): HintFix {
+
+ abstract fun isApplicable(caretOffset: Int): Boolean
+
+ override fun isSafe() = true
+
+ override fun isInteractive() = false
+
+}
+
+abstract class Inspection(open val element: KtElement) {
+
+ abstract val description: String
+
+ abstract fun isApplicable(): Boolean
+
+ fun hint(fileObject: FileObject) = Hint(
+ KotlinRule(HintSeverity.WARNING),
+ description,
+ fileObject,
+ OffsetRange(element.textRange.startOffset, element.textRange.endOffset),
+ emptyList(),
+ Priorities.HINT_PRIORITY
+ )
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ChangeReturnTypeIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ChangeReturnTypeIntention.kt
new file mode 100644
index 0000000..0368c11
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ChangeReturnTypeIntention.kt
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.diagnostics.Diagnostic
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
+import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
+import org.jetbrains.kotlin.idea.util.approximateWithResolvableType
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.psi.KtExpression
+import org.jetbrains.kotlin.psi.KtFunction
+import org.jetbrains.kotlin.psi.KtReturnExpression
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction
+import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.typeUtil.makeNullable
+import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
+import org.jetbrains.kotlin.psi.KtClassBody
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.resolve.scopes.LexicalScope
+import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ChangeReturnTypeIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private lateinit var function: KtFunction
+ private lateinit var type: KotlinType
+
+ private val activeDiagnostics = listOf(
+ Errors.CONSTANT_EXPECTED_TYPE_MISMATCH,
+ Errors.TYPE_MISMATCH,
+ Errors.NULL_FOR_NONNULL_TYPE,
+ Errors.TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH)
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ val bindingContext = analysisResult?.bindingContext ?: return false
+ val activeDiagnostic = getActiveDiagnostic(psi.textOffset, bindingContext.diagnostics) ?: return false
+ val expression = activeDiagnostic.psiElement.getNonStrictParentOfType(KtExpression::class.java) ?: return false
+
+ val expressionType = when (activeDiagnostic.factory) {
+ Errors.TYPE_MISMATCH -> {
+ val diagnosticWithParameters = Errors.TYPE_MISMATCH.cast(activeDiagnostic)
+ diagnosticWithParameters.b
+ }
+
+ Errors.NULL_FOR_NONNULL_TYPE -> {
+ val diagnosticWithParameters = Errors.NULL_FOR_NONNULL_TYPE.cast(activeDiagnostic)
+ val expectedType = diagnosticWithParameters.a
+ expectedType.makeNullable()
+ }
+
+ Errors.CONSTANT_EXPECTED_TYPE_MISMATCH -> bindingContext.getType(expression)
+
+ Errors.TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH -> {
+ val diagnosticWithParameters = Errors.TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.cast(activeDiagnostic)
+ diagnosticWithParameters.b
+ }
+
+ else -> null
+ } ?: return false
+
+ val expressionParent = expression.parent
+ val ktFunction = (if (expressionParent is KtReturnExpression) {
+ expressionParent.getTargetFunction(bindingContext)
+ } else {
+ PsiTreeUtil.getParentOfType(expression, KtFunction::class.java, true)
+ }) as? KtFunction ?: return false
+
+ return when {
+ QuickFixUtil.canFunctionOrGetterReturnExpression(ktFunction, expression) -> {
+ val scope = ktFunction.getResolutionScope(bindingContext)
+ type = expressionType.approximateWithResolvableType(scope, false)
+ function = ktFunction
+ true
+ }
+
+ expression is KtCallExpression -> {
+ type = expressionType
+ function = ktFunction
+ true
+ }
+
+ else -> false
+ }
+ }
+
+ private fun getActiveDiagnostic(offset: Int, diagnostics: Diagnostics): Diagnostic? {
+ return diagnostics.find { diagnostic ->
+ if (diagnostic.textRanges.isEmpty()) return@find false
+
+ val range = diagnostic.textRanges.first()
+ range.startOffset <= offset && offset <= range.endOffset && diagnostic.factory in activeDiagnostics
+ }
+ }
+
+ override fun getDescription(): String {
+ val functionName = function.name
+ val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
+ return if (functionName != null) {
+ "Change '$functionName' function return type to '$renderedType'"
+ } else {
+ "Change function return type to '$renderedType'"
+ }
+ }
+
+ override fun implement() {
+ val oldTypeRef = function.typeReference
+ val renderedType = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
+
+ if (oldTypeRef != null) {
+ val startOffset = oldTypeRef.textRange.startOffset
+ val endOffset = oldTypeRef.textRange.endOffset
+ doc.atomicChange {
+ remove(startOffset, endOffset - startOffset)
+ insertString(startOffset, renderedType, null)
+ }
+ } else {
+ val anchor = function.valueParameterList
+ if (anchor != null) {
+ doc.insertString(anchor.textRange.endOffset, ": $renderedType", null)
+ }
+ }
+ }
+
+}
+
+// from idea/idea-core/src/org/jetbrains/kotlin/idea/core/Utils.kt but without the second parameter
+fun PsiElement.getResolutionScope(bindingContext: BindingContext): LexicalScope {
+ for (parent in parentsWithSelf) {
+ if (parent is KtElement) {
+ val scope = bindingContext[BindingContext.LEXICAL_SCOPE, parent]
+ if (scope != null) return scope
+ }
+
+ if (parent is KtClassBody) {
+ val classDescriptor = bindingContext[BindingContext.CLASS, parent.getParent()] as? ClassDescriptorWithResolutionScopes
+ if (classDescriptor != null) {
+ return classDescriptor.scopeForMemberDeclarationResolution
+ }
+ }
+ }
+ error("Not in JetFile")
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertEnumToSealedClassIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertEnumToSealedClassIntention.kt
new file mode 100644
index 0000000..da2194e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertEnumToSealedClassIntention.kt
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertEnumToSealedClassIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtClass? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtClass::class.java) ?: return false
+ val element = expression ?: return false
+ element.nameIdentifier ?: return false
+ element.modifierList?.getModifier(KtTokens.ENUM_KEYWORD) ?: return false
+
+ return true
+ }
+
+ override fun getDescription() = "Convert to sealed class"
+
+ private fun KtClass.generateSealedClass(): String {
+ val builder = StringBuilder()
+
+ with (builder) {
+ append("sealed class $name")
+
+ val constructor = primaryConstructor?.text ?: ""
+
+ append(constructor).append(" {\n")
+
+ for (member in declarations) {
+ if (member !is KtEnumEntry) continue
+
+ append("object ${member.name} :")
+
+ val initializers = member.initializerList?.initializers ?: emptyList()
+ if (initializers.isNotEmpty()) {
+ append(initializers.joinToString { "$name${it.text}" })
+ } else append("$name()")
+
+ member.getBody()?.let { body -> append(body.text) }
+ append("\n")
+ }
+
+ getBody()?.let { body ->
+ body.declarations
+ .filter { it !is KtEnumEntry }
+ .forEach { append(it.text) }
+ }
+
+ append("}")
+ }
+ return builder.toString()
+ }
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val newText = element.generateSealedClass()
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, newText, null)
+ format(this, element.textRange.startOffset)
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertForEachToForLoopIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertForEachToForLoopIntention.kt
new file mode 100644
index 0000000..2626efa
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertForEachToForLoopIntention.kt
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertForEachToForLoopIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private val FOR_EACH_NAME = "forEach"
+ private val FOR_EACH_FQ_NAMES = listOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$FOR_EACH_NAME" }.toSet()
+
+ private var element: KtSimpleNameExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ element = psi.getNonStrictParentOfType(KtSimpleNameExpression::class.java) ?: return false
+ val expression = element ?: return false
+
+ val data = extractData(expression) ?: return false
+ if (data.functionLiteral.valueParameters.size > 1) return false
+ if (data.functionLiteral.bodyExpression == null) return false
+
+ return true
+ }
+
+ override fun getDescription() = "Convert 'forEach' to for loop"
+
+ override fun implement() {
+ val expression = element ?: return
+
+ val (expressionToReplace, receiver, functionLiteral) = extractData(expression)!!
+ val loop = generateLoop(functionLiteral, receiver)
+
+ val startOffset = expressionToReplace.textRange.startOffset
+ val lengthToDelete = expressionToReplace.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, loop, null)
+ format(this, expression.textRange.startOffset)
+ }
+ }
+
+ private data class Data(
+ val expressionToReplace: KtExpression,
+ val receiver: KtExpression,
+ val functionLiteral: KtLambdaExpression
+ )
+
+ private fun extractData(nameExpr: KtSimpleNameExpression): Data? {
+ val parent = nameExpr.parent
+ val expression = (when (parent) {
+ is KtCallExpression -> parent.parent as? KtDotQualifiedExpression
+ is KtBinaryExpression -> parent
+ else -> null
+ } ?: return null) as KtExpression
+
+ val context = analysisResult?.bindingContext ?: return null
+
+ val resolvedCall = expression.getResolvedCall(context) ?: return null
+ if (DescriptorUtils.getFqName(resolvedCall.resultingDescriptor).toString() !in FOR_EACH_FQ_NAMES) return null
+
+ val receiver = resolvedCall.call.explicitReceiver as? ExpressionReceiver ?: return null
+ val argument = resolvedCall.call.valueArguments.singleOrNull() ?: return null
+ val functionLiteral = argument.getArgumentExpression() as? KtLambdaExpression ?: return null
+
+ return Data(expression, receiver.expression, functionLiteral)
+ }
+
+ private fun generateLoop(functionLiteral: KtLambdaExpression, receiver: KtExpression): String {
+ val loopRange = KtPsiUtil.safeDeparenthesize(receiver)
+ val body = functionLiteral.bodyExpression!!
+ val parameter = functionLiteral.valueParameters.singleOrNull() ?: "it"
+
+ return "for ($parameter in ${loopRange.text}) { ${body.text} }"
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertPropertyInitializerToGetterIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertPropertyInitializerToGetterIntention.kt
new file mode 100644
index 0000000..476ca6d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertPropertyInitializerToGetterIntention.kt
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+
+class ConvertPropertyInitializerToGetterIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var property: KtProperty? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ property = psi.getNonStrictParentOfType(KtProperty::class.java) ?: return false
+ val element = property ?: return false
+
+ val initializer = element.initializer
+ return initializer != null && element.getter == null
+ && !element.isExtensionDeclaration()
+ && !element.isLocal
+ }
+
+ override fun getDescription() = "Convert property initializer to getter"
+
+ override fun implement() {
+ val element = property ?: return
+ val textWithGetter = getTextWithGetter(element)
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, textWithGetter, null)
+ format(this, element.textRange.startOffset)
+ }
+ }
+
+ private fun getTextWithGetter(element: KtProperty): String = with(StringBuilder()) {
+ append(element.modifierList?.text ?: "")
+
+ if (element.isVar) {
+ append(" var ")
+ } else append(" val ")
+
+ append(element.name)
+
+ val type = getTypeForDeclaration(element, analysisResult)
+
+ append(": ").append(type)
+
+ val initializer = element.initializer!!
+ append("\nget() = ").append(initializer.text)
+
+ val setter = element.setter
+ if (setter != null) {
+ append("\n").append(setter.text)
+ }
+
+ return toString()
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToBlockBodyIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToBlockBodyIntention.kt
new file mode 100644
index 0000000..b8af3ea
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToBlockBodyIntention.kt
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.util.PsiTreeUtil
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertToBlockBodyIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ val declaration = PsiTreeUtil.getParentOfType(psi, KtDeclarationWithBody::class.java) ?: return false
+ if (declaration is KtFunctionLiteral || declaration.hasBlockBody() || !declaration.hasBody()) return false
+
+ when (declaration) {
+ is KtNamedFunction -> {
+ val bindingContext = analysisResult?.bindingContext ?: return false
+ val returnType: KotlinType = declaration.returnType(bindingContext) ?: return false
+
+ // do not convert when type is implicit and unknown
+ if (!declaration.hasDeclaredReturnType() && returnType.isError) return false
+
+ return true
+ }
+
+ is KtPropertyAccessor -> return true
+
+ else -> error("Unknown declaration type: $declaration")
+ }
+ }
+
+ override fun getDescription() = "Convert to block body"
+
+ override fun implement() {
+ val declaration = PsiTreeUtil.getParentOfType(psi, KtDeclarationWithBody::class.java) ?: return
+ val context = analysisResult?.bindingContext ?: return
+
+ val shouldSpecifyType = declaration is KtNamedFunction
+ && !declaration.hasDeclaredReturnType()
+ && !KotlinBuiltIns.isUnit(declaration.returnType(context)!!)
+
+ val factory = KtPsiFactory(declaration)
+
+ replaceBody(declaration, factory, context, shouldSpecifyType)
+ }
+
+ private fun convert(declaration: KtDeclarationWithBody, bindingContext: BindingContext, factory: KtPsiFactory): KtExpression {
+ val body = declaration.bodyExpression!!
+
+ fun generateBody(returnsValue: Boolean): KtExpression {
+ val bodyType = bindingContext.getType(body)
+ val needReturn = returnsValue &&
+ (bodyType == null || (!KotlinBuiltIns.isUnit(bodyType) && !KotlinBuiltIns.isNothing(bodyType)))
+
+ val expression = factory.createExpression(body.text)
+ val block: KtBlockExpression = if (needReturn) {
+ factory.createBlock("return xyz")
+ } else {
+ return factory.createBlock(expression.text)
+ }
+ val returnExpression = PsiTreeUtil.getChildOfType(block, KtReturnExpression::class.java)
+ val returned = returnExpression?.returnedExpression ?: return factory.createBlock("return ${expression.text}")
+ if (KtPsiUtil.areParenthesesNecessary(expression, returned, returnExpression)) {
+ return factory.createBlock("return (${expression.text})")
+ }
+ return factory.createBlock("return ${expression.text}")
+ }
+
+ return when (declaration) {
+ is KtNamedFunction -> {
+ val returnType = declaration.returnType(bindingContext)!!
+ generateBody(!KotlinBuiltIns.isUnit(returnType) && !KotlinBuiltIns.isNothing(returnType))
+ }
+
+ is KtPropertyAccessor -> generateBody(declaration.isGetter)
+
+ else -> throw RuntimeException("Unknown declaration type: $declaration")
+ }
+ }
+
+ private fun replaceBody(declaration: KtDeclarationWithBody, factory: KtPsiFactory,
+ context: BindingContext, shouldSpecifyType: Boolean) {
+ val newBody = convert(declaration, context, factory)
+ var newBodyText = newBody.node.text
+
+ val anchorToken = declaration.equalsToken
+ if (anchorToken!!.nextSibling !is PsiWhiteSpace) {
+ newBodyText = "${factory.createWhiteSpace().text}$newBodyText"
+ }
+
+ val startOffset = anchorToken.textRange.startOffset
+ val endOffset = declaration.bodyExpression!!.textRange.endOffset
+
+ doc.atomicChange {
+ remove(startOffset, endOffset - startOffset)
+ insertString(startOffset, newBodyText, null)
+ if (shouldSpecifyType) {
+ specifyType(declaration, factory, context)
+ }
+ format(this, declaration.textRange.startOffset)
+ }
+ }
+
+ private fun specifyType(declaration: KtDeclarationWithBody, factory: KtPsiFactory, context: BindingContext) {
+ val returnType = (declaration as KtNamedFunction).returnType(context).toString()
+ val stringToInsert = listOf(factory.createColon(), factory.createWhiteSpace())
+ .joinToString(separator = "") { it.text } + returnType
+
+ doc.insertString(declaration.valueParameterList!!.textRange.endOffset, stringToInsert, null)
+ }
+
+}
+
+private fun KtNamedFunction.returnType(context: BindingContext): KotlinType? {
+ val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, this] ?: return null
+ return (descriptor as FunctionDescriptor).returnType
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToConcatenatedStringIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToConcatenatedStringIntention.kt
new file mode 100644
index 0000000..ec43634
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToConcatenatedStringIntention.kt
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.hints.atomicChange
+import org.jetbrains.kotlin.reformatting.moveCursorTo
+
+class ConvertToConcatenatedStringIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtStringTemplateExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtStringTemplateExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ if (element.lastChild.node.elementType != KtTokens.CLOSING_QUOTE) return false
+ return element.entries.any { it is KtStringTemplateEntryWithExpression }
+ }
+
+ override fun getDescription() = "Convert template to concatenated string"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val tripleQuoted = isTripleQuoted(element.text!!)
+ val quote = if (tripleQuoted) "\"\"\"" else "\""
+ val entries = element.entries
+
+ val text = entries
+ .filterNot { it is KtStringTemplateEntryWithExpression && it.expression == null }
+ .mapIndexed { index, entry ->
+ entry.toSeparateString(quote, convertExplicitly = (index == 0), isFinalEntry = (index == entries.lastIndex))
+ }
+ .joinToString(separator = "+")
+ .replace("""$quote+$quote""", "")
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, text, null)
+ moveCursorTo(element.textRange.startOffset)
+ }
+ }
+
+ // copied from IDEA plugin
+
+ private fun isTripleQuoted(str: String) = str.startsWith("\"\"\"") && str.endsWith("\"\"\"")
+
+ private fun KtStringTemplateEntry.toSeparateString(quote: String, convertExplicitly: Boolean, isFinalEntry: Boolean): String {
+ if (this !is KtStringTemplateEntryWithExpression) {
+ return text.quote(quote)
+ }
+
+ val expression = expression!! // checked before
+
+ val text = if (needsParenthesis(expression, isFinalEntry))
+ "(${expression.text})"
+ else
+ expression.text
+
+ return if (convertExplicitly && !expression.isStringExpression())
+ "$text.toString()"
+ else
+ text
+ }
+
+ private fun needsParenthesis(expression: KtExpression, isFinalEntry: Boolean): Boolean = when (expression) {
+ is KtBinaryExpression -> true
+ is KtIfExpression -> expression.`else` !is KtBlockExpression && !isFinalEntry
+ else -> false
+ }
+
+ private fun String.quote(quote: String) = "$quote${this}$quote"
+
+ private fun KtExpression.isStringExpression(): Boolean {
+ val context = analysisResult?.bindingContext ?: return false
+ return KotlinBuiltIns.isString(context.getType(this))
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToExpressionBodyIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToExpressionBodyIntention.kt
new file mode 100644
index 0000000..1e8dbc2
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToExpressionBodyIntention.kt
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiRecursiveElementWalkingVisitor
+import com.intellij.psi.util.PsiTreeUtil
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.reformatting.moveCursorTo
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertToExpressionBodyIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ val element = PsiTreeUtil.getParentOfType(psi, KtDeclarationWithBody::class.java) ?: return false
+ if (element is KtConstructor<*>) return false
+ val value = calcValue(element) ?: return false
+
+ return !value.anyDescendantOfType<KtReturnExpression>(
+ canGoInside = { it !is KtFunctionLiteral && it !is KtNamedFunction && it !is KtPropertyAccessor }
+)
+ }
+
+ override fun getDescription() = "Convert to expression body"
+
+ override fun implement() {
+ val element = PsiTreeUtil.getParentOfType(psi, KtDeclarationWithBody::class.java) ?: return
+ val expression = calcValue(element) ?: return
+ val context = analysisResult?.bindingContext ?: return
+ val block = element.blockExpression() ?: return
+
+ if (element !is KtCallableDeclaration) return
+
+ val colon = element.colon?.textRange?.startOffset ?: element.bodyExpression!!.textRange.startOffset
+
+ val type = if (!element.hasDeclaredReturnType()
+ && element is KtNamedFunction
+ && block.statements.isNotEmpty()) {
+ val valueType = context.getType(expression)
+ if (valueType == null || KotlinBuiltIns.isUnit(valueType)) {
+ KotlinBuiltIns.FQ_NAMES.unit.shortName().asString()
+ } else return
+ } else if (element.hasDeclaredReturnType()) {
+ element.typeReference!!.text
+ } else ""
+
+ val endOffset = element.bodyExpression!!.textRange.endOffset
+
+ doc.atomicChange {
+ remove(colon, endOffset - colon)
+ insertString(colon, ": $type = ${expression.text}", null)
+ moveCursorTo(colon)
+ }
+ }
+
+ private fun KtDeclarationWithBody.blockExpression() = when (this) {
+ is KtFunctionLiteral -> null
+ else -> {
+ val body = bodyExpression
+ if (!hasBlockBody() || body !is KtBlockExpression) null else body
+ }
+ }
+
+ private fun calcValue(declaration: KtDeclarationWithBody): KtExpression? {
+ val body = declaration.blockExpression() ?: return null
+ return calcValue(body)
+ }
+
+ private fun calcValue(body: KtBlockExpression): KtExpression? {
+ val bodyStatements = body.statements
+ if (bodyStatements.isEmpty()) {
+ return KtPsiFactory(body).createExpression("Unit")
+ }
+ val statement = bodyStatements.singleOrNull() ?: return null
+ when (statement) {
+ is KtReturnExpression -> {
+ return statement.returnedExpression
+ }
+
+ //TODO: IMO this is not good code, there should be a way to detect that JetExpression does not have value
+ is KtDeclaration, is KtLoopExpression -> return null // is JetExpression but does not have value
+
+ else -> {
+ if (statement is KtBinaryExpression && statement.operationToken in KtTokens.ALL_ASSIGNMENTS) return null // assignment does not have value
+
+ val context = analysisResult?.bindingContext ?: return null
+ val expressionType = context.getType(statement) ?: return null
+ val isUnit = KotlinBuiltIns.isUnit(expressionType)
+ if (!isUnit && !KotlinBuiltIns.isNothing(expressionType)) return null
+ if (isUnit) {
+ if (statement.hasResultingIfWithoutElse()) {
+ return null
+ }
+ val resultingWhens = statement.resultingWhens()
+ if (resultingWhens.any { it.elseExpression == null && context.get(BindingContext.EXHAUSTIVE_WHEN, it) != true }) {
+ return null
+ }
+ }
+ return statement
+ }
+ }
+ }
+
+}
+
+fun KtExpression?.hasResultingIfWithoutElse(): Boolean = when (this) {
+ is KtIfExpression -> `else` == null || then.hasResultingIfWithoutElse() || `else`.hasResultingIfWithoutElse()
+ is KtWhenExpression -> entries.any { it.expression.hasResultingIfWithoutElse() }
+ is KtBinaryExpression -> left.hasResultingIfWithoutElse() || right.hasResultingIfWithoutElse()
+ is KtUnaryExpression -> baseExpression.hasResultingIfWithoutElse()
+ is KtBlockExpression -> statements.lastOrNull().hasResultingIfWithoutElse()
+ else -> false
+}
+
+fun KtExpression.resultingWhens(): List<KtWhenExpression> = when (this) {
+ is KtWhenExpression -> listOf(this) + entries.map { it.expression?.resultingWhens() ?: listOf() }.flatten()
+ is KtIfExpression -> (then?.resultingWhens() ?: listOf()) + (`else`?.resultingWhens() ?: listOf())
+ is KtBinaryExpression -> (left?.resultingWhens() ?: listOf()) + (right?.resultingWhens() ?: listOf())
+ is KtUnaryExpression -> this.baseExpression?.resultingWhens() ?: listOf()
+ is KtBlockExpression -> statements.lastOrNull()?.resultingWhens() ?: listOf()
+ else -> listOf()
+}
+
+inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(crossinline canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): Boolean =
+ findDescendantOfType(canGoInside, predicate) != null
+
+inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(crossinline canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): T? {
+ var result: T? = null
+ this.accept(object : PsiRecursiveElementWalkingVisitor() {
+ override fun visitElement(element: PsiElement) {
+ if (element is T && predicate(element)) {
+ result = element
+ stopWalking()
+ return
+ }
+
+ if (canGoInside(element)) {
+ super.visitElement(element)
+ }
+ }
+ })
+ return result
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToStringTemplateIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToStringTemplateIntention.kt
new file mode 100644
index 0000000..6da6b3b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertToStringTemplateIntention.kt
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.psi.util.PsiUtilCore
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.reformatting.moveCursorTo
+import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertToStringTemplateIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+ private var expression: KtBinaryExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtBinaryExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ return element.isApplicable()
+ }
+
+ override fun getDescription() = "Convert concatenation to template"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val text = buildReplacement(element).text
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, text, null)
+ moveCursorTo(element.textRange.startOffset)
+ }
+ }
+
+}
+
+class ConvertToStringTemplateInspection(val parserResult: KotlinParserResult,
+ override val element: KtElement) : Inspection(element) {
+
+ override val description = "Concatenation can be replaced by template"
+
+ override fun isApplicable(): Boolean {
+ if (element !is KtBinaryExpression) return false
+
+ return element.isApplicable()
+ }
+}
+
+// copied from IDEA plugin
+
+private fun KtBinaryExpression.isApplicable(): Boolean {
+ if (!isApplicableToNoParentCheck(this)) return false
+
+ val parent = this.parent
+ if (parent is KtBinaryExpression && isApplicableToNoParentCheck(parent)) return false
+
+ return true
+}
+
+private fun buildReplacement(expression: KtBinaryExpression): KtStringTemplateExpression {
+ val rightText = buildText(expression.right, false)
+ return fold(expression.left, rightText, KtPsiFactory(expression))
+}
+
+private fun fold(left: KtExpression?, right: String, factory: KtPsiFactory): KtStringTemplateExpression {
+ val forceBraces = !right.isEmpty() && right.first() != '$' && right.first().isJavaIdentifierPart()
+
+ return if (left is KtBinaryExpression && isApplicableToNoParentCheck(left)) {
+ val leftRight = buildText(left.right, forceBraces)
+ fold(left.left, "$leftRight$right", factory)
+ } else {
+ val leftText = buildText(left, forceBraces)
+ factory.createExpression("\"$leftText$right\"") as KtStringTemplateExpression
+ }
+}
+
+private fun buildText(expr: KtExpression?, forceBraces: Boolean): String {
+ if (expr == null) return ""
+ val expression = KtPsiUtil.safeDeparenthesize(expr)
+ val expressionText = expression.text
+ when (expression) {
+ is KtConstantExpression -> {
+ val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
+ val type = bindingContext.getType(expression)!!
+
+ if (KotlinBuiltIns.isChar(type)) {
+ val value = expressionText.removePrefix("'").removeSuffix("'")
+ return when (value) { // escape double quote and unescape single one
+ "\"" -> "\\\""
+ "\\'" -> "'"
+ else -> value
+ }
+ }
+
+ val constant = ConstantExpressionEvaluator.getConstant(expression, bindingContext)
+ val stringValue = constant?.getValue(type).toString()
+ if (stringValue == expressionText) {
+ return StringUtil.escapeStringCharacters(stringValue)
+ }
+ }
+
+ is KtStringTemplateExpression -> {
+ val base = if (expressionText.startsWith("\"\"\"") && expressionText.endsWith("\"\"\"")) {
+ val unquoted = expressionText.substring(3, expressionText.length - 3)
+ StringUtil.escapeStringCharacters(unquoted)
+ } else {
+ StringUtil.unquoteString(expressionText)
+ }
+
+ if (forceBraces) {
+ if (base.endsWith('$')) {
+ return "${base.dropLast(1)}\\$"
+ } else {
+ val lastPart = expression.children.lastOrNull()
+ if (lastPart is KtSimpleNameStringTemplateEntry) {
+ return "${base.dropLast(lastPart.textLength)}\${${lastPart.text.drop(1)}}"
+ }
+ }
+ }
+ return base
+ }
+
+ is KtNameReferenceExpression ->
+ return "$${if (forceBraces) "{$expressionText}" else expressionText}"
+ }
+
+ return "\${$expressionText}"
+}
+
+private fun isApplicableToNoParentCheck(expression: KtBinaryExpression): Boolean {
+ if (expression.operationToken != KtTokens.PLUS) return false
+ val expressionType = expression.analyze(BodyResolveMode.PARTIAL).getType(expression)
+ if (!KotlinBuiltIns.isString(expressionType)) return false
+ return isSuitable(expression)
+}
+
+private fun isSuitable(expression: KtExpression): Boolean {
+ if (expression is KtBinaryExpression && expression.operationToken == KtTokens.PLUS) {
+ return isSuitable(expression.left ?: return false) && isSuitable(expression.right ?: return false)
+ }
+
+ if (PsiUtilCore.hasErrorElementChild(expression)) return false
+ if (expression.textContains('\n')) return false
+ return true
+}
+
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertTryFinallyToUseCallIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertTryFinallyToUseCallIntention.kt
new file mode 100644
index 0000000..67437fe
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertTryFinallyToUseCallIntention.kt
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.descriptors.VariableDescriptor
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.psiUtil.contentRange
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
+import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
+import org.jetbrains.kotlin.types.typeUtil.supertypes
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertTryFinallyToUseCallIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var tryExpression: KtTryExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ tryExpression = psi.getNonStrictParentOfType(KtTryExpression::class.java) ?: return false
+ val element = tryExpression ?: return false
+
+ return element.isApplicable(analysisResult)
+ }
+
+ override fun getDescription() = "Convert try-finally to .use()"
+
+ override fun implement() {
+ val element = tryExpression ?: return
+
+ val finallySection = element.finallyBlock!!
+ val finallyExpression = finallySection.finalExpression.statements.single()
+ val finallyExpressionReceiver = (finallyExpression as? KtQualifiedExpression)?.receiverExpression
+ val resourceReference = finallyExpressionReceiver as? KtNameReferenceExpression
+ val resourceName = resourceReference?.getReferencedNameAsName()
+
+ val useExpression = StringBuilder()
+
+ with(useExpression) {
+ if (resourceName != null) {
+ append(resourceName).append(".")
+ } else if (finallyExpressionReceiver is KtThisExpression) {
+ append(finallyExpressionReceiver.text).append(".")
+ }
+
+ append("use {")
+
+ if (resourceName != null) {
+ append(resourceName).append("->")
+ }
+ append("\n")
+
+ element.tryBlock.contentRange().forEach { append(it.text).append("\n") }
+
+ append("}")
+ }
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, useExpression.toString(), null)
+ format(this, element.textRange.startOffset)
+ }
+ }
+}
+
+class ConvertTryFinallyToUseCallInspection(val parserResult: KotlinParserResult,
+ override val element: KtElement) : Inspection(element) {
+
+ override val description = "Usage of try-finally instead of .use()"
+
+ override fun isApplicable(): Boolean {
+ if (element !is KtTryExpression) return false
+
+ return element.isApplicable(parserResult.analysisResult?.analysisResult)
+ }
+}
+
+private fun KtTryExpression.isApplicable(analysisResult: AnalysisResult?): Boolean {
+ val finallySection = finallyBlock ?: return false
+ val finallyExpression = finallySection.finalExpression.statements.singleOrNull() ?: return false
+ if (catchClauses.isNotEmpty()) return false
+
+ val context = analysisResult?.bindingContext ?: return false
+ val resolvedCall = finallyExpression.getResolvedCall(context) ?: return false
+ if (resolvedCall.candidateDescriptor.name.asString() != "close") return false
+ if (resolvedCall.extensionReceiver != null) return false
+ val receiver = resolvedCall.dispatchReceiver ?: return false
+ if (receiver.type.supertypes().all {
+ it.constructor.declarationDescriptor?.fqNameSafe?.asString().let {
+ it != "java.io.Closeable" && it != "java.lang.AutoCloseable"
+ }
+ }) return false
+
+ when (receiver) {
+ is ExpressionReceiver -> {
+ val expression = receiver.expression
+ if (expression !is KtThisExpression) {
+ val resourceReference = expression as? KtReferenceExpression ?: return false
+ val resourceDescriptor =
+ context[BindingContext.REFERENCE_TARGET, resourceReference] as? VariableDescriptor ?: return false
+ if (resourceDescriptor.isVar) return false
+ }
+ }
+ is ImplicitReceiver -> {
+ }
+ else -> return false
+ }
+
+ return true
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt
new file mode 100644
index 0000000..039764f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ConvertTwoComparisonsToRangeCheckIntention.kt
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import com.intellij.psi.tree.IElementType
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.calls.callUtil.getType
+import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ConvertTwoComparisonsToRangeCheckIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtBinaryExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtBinaryExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ return generateRangeExpressionData(element) != null
+ }
+
+ override fun getDescription() = "Convert to range check"
+
+ override fun implement() {
+ val element = expression ?: return
+ val rangeData = generateRangeExpressionData(element) ?: return
+
+ val text = "${rangeData.value.text} in ${rangeData.min}..${rangeData.max}"
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, text, null)
+ }
+ }
+
+ // copied from IDEA plugin
+
+ private data class RangeExpressionData(val value: KtExpression, val min: String, val max: String)
+
+ private fun KtExpression.unwrapBlockOrParenthesis(): KtExpression {
+ val innerExpression = KtPsiUtil.safeDeparenthesize(this)
+ if (innerExpression is KtBlockExpression) {
+ val statement = innerExpression.statements.singleOrNull() ?: return this
+ return KtPsiUtil.safeDeparenthesize(statement)
+ }
+ return innerExpression
+ }
+
+ private fun KtExpression.evaluatesTo(other: KtExpression) = unwrapBlockOrParenthesis().text == other.text
+
+ private fun generateRangeExpressionData(condition: KtBinaryExpression): RangeExpressionData? {
+ if (condition.operationToken != KtTokens.ANDAND) return null
+ val firstCondition = condition.left as? KtBinaryExpression ?: return null
+ val secondCondition = condition.right as? KtBinaryExpression ?: return null
+ val firstOpToken = firstCondition.operationToken
+ val secondOpToken = secondCondition.operationToken
+ val firstLeft = firstCondition.left ?: return null
+ val firstRight = firstCondition.right ?: return null
+ val secondLeft = secondCondition.left ?: return null
+ val secondRight = secondCondition.right ?: return null
+
+ fun IElementType.isStrictComparison() = this == KtTokens.GT || this == KtTokens.LT
+
+ val firstStrict = firstOpToken.isStrictComparison()
+ val secondStrict = secondOpToken.isStrictComparison()
+
+ fun IElementType.orderLessAndGreater(left: KtExpression, right: KtExpression): Pair<KtExpression, KtExpression>? = when (this) {
+ KtTokens.GTEQ, KtTokens.GT -> right to left
+ KtTokens.LTEQ, KtTokens.LT -> left to right
+ else -> null
+ }
+
+ val (firstLess, firstGreater) = firstOpToken.orderLessAndGreater(firstLeft, firstRight) ?: return null
+ val (secondLess, secondGreater) = secondOpToken.orderLessAndGreater(secondLeft, secondRight) ?: return null
+
+ return generateRangeExpressionData(firstLess, firstGreater, firstStrict, secondLess, secondGreater, secondStrict)
+ }
+
+ private fun KtExpression.isSimple() = this is KtConstantExpression || this is KtNameReferenceExpression
+
+ private fun generateRangeExpressionData(
+ firstLess: KtExpression, firstGreater: KtExpression, firstStrict: Boolean,
+ secondLess: KtExpression, secondGreater: KtExpression, secondStrict: Boolean
+ ) = when {
+ firstGreater !is KtConstantExpression && firstGreater.evaluatesTo(secondLess) ->
+ generateRangeExpressionData(firstGreater,
+ min = firstLess,
+ max = secondGreater,
+ incrementMinByOne = firstStrict,
+ decrementMaxByOne = secondStrict)
+ firstLess !is KtConstantExpression && firstLess.evaluatesTo(secondGreater) ->
+ generateRangeExpressionData(firstLess,
+ min = secondLess,
+ max = firstGreater,
+ incrementMinByOne = secondStrict,
+ decrementMaxByOne = firstStrict)
+ else ->
+ null
+ }
+
+ private fun generateRangeExpressionData(
+ value: KtExpression, min: KtExpression, max: KtExpression, incrementMinByOne: Boolean, decrementMaxByOne: Boolean
+ ): RangeExpressionData? {
+ fun KtExpression.getChangeBy(number: Int): String? {
+ val context = analyze()
+ val type = getType(context) ?: return null
+ if (!type.isValidTypeForIncrementDecrementByOne()) return null
+
+ when (this) {
+ is KtConstantExpression -> {
+ val constantValue = ConstantExpressionEvaluator.getConstant(this, context)?.getValue(type) ?: return null
+ return when {
+ KotlinBuiltIns.isInt(type) -> (constantValue as Int + number).toString()
+ KotlinBuiltIns.isLong(type) -> (constantValue as Long + number).toString()
+ KotlinBuiltIns.isChar(type) -> "'${constantValue as Char + number}'"
+ else -> return null
+ }
+ }
+ else -> return if (number >= 0) "($text + $number)" else "($text - ${-number})"
+ }
+ }
+
+ // To avoid possible side effects
+ if (!min.isSimple() || !max.isSimple()) return null
+
+ if (incrementMinByOne || decrementMaxByOne) {
+ if (!value.getType(value.analyze()).isValidTypeForIncrementDecrementByOne()) return null
+ }
+
+ val minText = if (incrementMinByOne) min.getChangeBy(1) else min.text
+ val maxText = if (decrementMaxByOne) max.getChangeBy(-1) else max.text
+ return RangeExpressionData(value, minText ?: return null, maxText ?: return null)
+ }
+
+ private fun KotlinType?.isValidTypeForIncrementDecrementByOne(): Boolean {
+ this ?: return false
+ return KotlinBuiltIns.isInt(this) ||
+ KotlinBuiltIns.isLong(this) ||
+ KotlinBuiltIns.isShort(this) ||
+ KotlinBuiltIns.isByte(this) ||
+ KotlinBuiltIns.isChar(this)
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/MergeIfsIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/MergeIfsIntention.kt
new file mode 100644
index 0000000..9c6f936
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/MergeIfsIntention.kt
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class MergeIfsIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtIfExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtIfExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ if (element.`else` != null) return false
+ val then = element.then ?: return false
+
+ val nestedIf = then.nestedIf() ?: return false
+ if (nestedIf.`else` != null) return false
+
+ return true
+ }
+
+ override fun getDescription() = "Merge 'if's"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val nestedIf = element.then?.nestedIf() ?: return
+ val condition = element.condition ?: return
+ val secondCondition = nestedIf.condition ?: return
+ val nestedBody = nestedIf.then ?: return
+
+ val text = "if (${condition.text} && ${secondCondition.text}) ${nestedBody.text} "
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, text, null)
+ format(this, element.textRange.startOffset)
+ }
+ }
+
+ private fun KtExpression.nestedIf() = when (this) {
+ is KtBlockExpression -> this.statements.singleOrNull() as? KtIfExpression
+ is KtIfExpression -> this
+ else -> null
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveBracesIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveBracesIntention.kt
new file mode 100644
index 0000000..4796a4a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveBracesIntention.kt
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.KtNodeTypes
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class RemoveBracesIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var desc: String = "Remove braces"
+ private var expression: KtElement? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtElement::class.java) ?: return false
+ val element = expression ?: return false
+
+ val block = element.findChildBlock() ?: return false
+ val singleStatement = block.statements.singleOrNull() ?: return false
+ val container = block.parent
+ when (container) {
+ is KtContainerNode -> {
+ if (singleStatement is KtIfExpression && container.parent is KtIfExpression) return false
+
+ val description = container.description() ?: return false
+ desc = "Remove braces from '$description' statement"
+ return true
+ }
+ is KtWhenEntry -> {
+ desc = "Remove braces from 'when' entry"
+ return singleStatement !is KtNamedDeclaration
+ }
+ else -> return false
+ }
+ }
+
+ override fun getDescription() = desc
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val block = element.findChildBlock() ?: return
+ val statement = block.statements.single()
+
+ val startOffset = block.textRange.startOffset
+ val lengthToDelete = block.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, statement.text, null)
+ format(this, element.textRange.startOffset)
+ }
+ }
+
+ private fun KtElement.findChildBlock() = when (this) {
+ is KtBlockExpression -> this
+ is KtLoopExpression -> body as? KtBlockExpression
+ is KtWhenEntry -> expression as? KtBlockExpression
+ else -> null
+ }
+
+}
+
+fun KtContainerNode.description(): String? {
+ when (node.elementType) {
+ KtNodeTypes.THEN -> return "if"
+ KtNodeTypes.ELSE -> return "else"
+ KtNodeTypes.BODY -> {
+ when (parent) {
+ is KtWhileExpression -> return "while"
+ is KtDoWhileExpression -> return "do...while"
+ is KtForExpression -> return "for"
+ }
+ }
+ }
+ return null
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyClassBodyIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyClassBodyIntention.kt
new file mode 100644
index 0000000..12b01ce
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyClassBodyIntention.kt
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+
+class RemoveEmptyClassBodyIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtClassBody? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtClassBody::class.java) ?: return false
+ val element = expression ?: return false
+
+ return element.isApplicable()
+ }
+
+ override fun getDescription() = "Remove empty class body"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.remove(startOffset, lengthToDelete)
+ }
+}
+
+class RemoveEmptyClassBodyInspection(val parserResult: KotlinParserResult,
+ override val element: KtElement) : Inspection(element) {
+
+ override val description = "Empty class body"
+
+ override fun isApplicable(): Boolean {
+ if (element !is KtClassBody) return false
+
+ return element.isApplicable()
+ }
+}
+
+private fun KtClassBody.isApplicable(): Boolean {
+ getNonStrictParentOfType(KtObjectDeclaration::class.java)?.let {
+ if (it.isObjectLiteral()) return false
+ }
+
+ getNonStrictParentOfType(KtClass::class.java)?.let {
+ if (!it.isTopLevel() && it.getNextSiblingIgnoringWhitespaceAndComments() is KtSecondaryConstructor) return false
+ }
+
+ return text.replace("{", "").replace("}", "").isBlank()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyParenthesesFromLambdaCallIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyParenthesesFromLambdaCallIntention.kt
new file mode 100644
index 0000000..bb0df3c
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyParenthesesFromLambdaCallIntention.kt
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.*
+
+class RemoveEmptyParenthesesFromLambdaCallIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtValueArgumentList? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtValueArgumentList::class.java) ?: return false
+ val element = expression ?: return false
+
+ if (element.arguments.isNotEmpty()) return false
+ val parent = element.parent as? KtCallExpression ?: return false
+
+ return (parent.lambdaArguments.count() == 1)
+ }
+
+ override fun getDescription() = "Remove unnecessary parentheses from function call with lambda"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.remove(startOffset, lengthToDelete)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyPrimaryConstructorIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyPrimaryConstructorIntention.kt
new file mode 100644
index 0000000..d157bee
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptyPrimaryConstructorIntention.kt
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.containingClass
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+
+class RemoveEmptyPrimaryConstructorIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtPrimaryConstructor? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtPrimaryConstructor::class.java) ?: return false
+ val element = expression ?: return false
+
+ return element.isApplicable()
+ }
+
+ override fun getDescription() = "Remove empty primary constructor"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.remove(startOffset, lengthToDelete)
+ }
+}
+
+class RemoveEmptyPrimaryConstructorInspection(val parserResult: KotlinParserResult,
+ override val element: KtElement) : Inspection(element) {
+
+ override val description = "Empty primary constructor"
+
+ override fun isApplicable(): Boolean {
+ if (element !is KtPrimaryConstructor) return false
+
+ return element.isApplicable()
+ }
+
+}
+
+private fun KtPrimaryConstructor.isApplicable() = when {
+ valueParameters.isNotEmpty() -> false
+ annotations.isNotEmpty() -> false
+ modifierList?.text?.isBlank() == false -> false
+ containingClass()?.secondaryConstructors?.isNotEmpty() == true -> false
+ else -> true
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptySecondaryConstructorIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptySecondaryConstructorIntention.kt
new file mode 100644
index 0000000..75decfe
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveEmptySecondaryConstructorIntention.kt
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+
+class RemoveEmptySecondaryConstructorIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtBlockExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtBlockExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ return element.isApplicable()
+ }
+
+ override fun getDescription() = "Remove empty secondary constructor"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.remove(startOffset, lengthToDelete)
+ }
+}
+
+class RemoveEmptySecondaryConstructorInspection(val parserResult: KotlinParserResult,
+ override val element: KtElement) : Inspection(element) {
+
+ override val description = "Empty secondary constructor"
+
+ override fun isApplicable(): Boolean {
+ if (element !is KtBlockExpression) return false
+
+ return element.isApplicable()
+ }
+
+}
+
+private fun KtBlockExpression.isApplicable(): Boolean {
+ if(parent !is KtSecondaryConstructor) return false
+ if(statements.isNotEmpty()) return false
+
+ return text.replace("{", "").replace("}", "").isBlank()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveExplicitTypeIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveExplicitTypeIntention.kt
new file mode 100644
index 0000000..3573e0d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/RemoveExplicitTypeIntention.kt
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.KtCallableDeclaration
+import org.jetbrains.kotlin.psi.KtCodeFragment
+import org.jetbrains.kotlin.psi.KtNamedFunction
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer
+import com.intellij.psi.PsiElement
+
+class RemoveExplicitTypeIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ val element = psi.getNonStrictParentOfType(KtCallableDeclaration::class.java) ?: return false
+
+ if (element.containingFile is KtCodeFragment) return false
+ if (element.typeReference == null) return false
+
+ val initializer = (element as? KtDeclarationWithInitializer)?.initializer
+ if (initializer != null && initializer.textRange.containsOffset(caretOffset)) return false
+
+ return when (element) {
+ is KtProperty -> initializer != null
+ is KtNamedFunction -> !element.hasBlockBody() && initializer != null
+ is KtParameter -> element.isLoopParameter
+ else -> false
+ }
+ }
+
+ override fun getDescription() = "Remove explicit type specification"
+
+ override fun implement() {
+ val element = psi.getNonStrictParentOfType(KtCallableDeclaration::class.java) ?: return
+ val anchor = getAnchor(element) ?: return
+
+ val endOffset = anchor.textRange.endOffset
+ val endOfType = element.typeReference!!.textRange.endOffset
+
+ doc.remove(endOffset, endOfType - endOffset)
+ }
+
+}
+
+fun getAnchor(element: KtCallableDeclaration): PsiElement? = when (element) {
+ is KtProperty, is KtParameter -> element.nameIdentifier
+ is KtNamedFunction -> element.valueParameterList
+ else -> null
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ReplaceSizeCheckWithIsNotEmptyIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ReplaceSizeCheckWithIsNotEmptyIntention.kt
new file mode 100644
index 0000000..9df66b8
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ReplaceSizeCheckWithIsNotEmptyIntention.kt
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.psi.psiUtil.*
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ReplaceSizeCheckWithIsNotEmptyInspection(val parserResult: KotlinParserResult,
+ override val element: KtElement) : Inspection(element) {
+ override val description = "Use 'isNotEmpty' instead of size check"
+
+ override fun isApplicable(): Boolean {
+ if (element !is KtBinaryExpression) return false
+
+ return element.isApplicable(parserResult.analysisResult?.analysisResult)
+ }
+}
+
+class ReplaceSizeCheckWithIsNotEmptyIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtBinaryExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtBinaryExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ return element.isApplicable(analysisResult)
+ }
+
+ override fun getDescription() = "Replace size check with 'isNotEmpty'"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val target = getTargetExpression(element) as? KtDotQualifiedExpression ?: return
+
+ val newText = "${target.receiverExpression.text}.isNotEmpty()"
+
+ val startOffset = element.textRange.startOffset
+ val lengthToDelete = element.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, newText, null)
+ }
+
+ }
+
+}
+
+fun KtElement?.isZero() = this?.text == "0"
+
+fun KtElement?.isOne() = this?.text == "1"
+
+private fun KtExpression.isExpressionOfTypeOrSubtype(context: BindingContext,
+ predicate: (KotlinType) -> Boolean): Boolean {
+ val returnType = getResolvedCall(context)?.resultingDescriptor?.returnType
+ return returnType != null && (returnType.constructor.supertypes + returnType).any(predicate)
+}
+
+fun KtElement?.isSizeOrLength(context: BindingContext): Boolean {
+ if (this !is KtDotQualifiedExpression) return false
+
+ return when (selectorExpression?.text) {
+ "size" -> receiverExpression.isExpressionOfTypeOrSubtype(context) { type ->
+ KotlinBuiltIns.isArray(type) ||
+ KotlinBuiltIns.isPrimitiveArray(type) ||
+ KotlinBuiltIns.isCollectionOrNullableCollection(type) ||
+ KotlinBuiltIns.isMapOrNullableMap(type)
+ }
+ "length" -> receiverExpression.isExpressionOfTypeOrSubtype(context, KotlinBuiltIns::isCharSequenceOrNullableCharSequence)
+ else -> false
+ }
+}
+
+private fun getTargetExpression(element: KtBinaryExpression): KtExpression? = when (element.operationToken) {
+ KtTokens.EXCLEQ -> when {
+ element.right.isZero() -> element.left
+ element.left.isZero() -> element.right
+ else -> null
+ }
+ KtTokens.GT -> if (element.right.isZero()) element.left else null
+ KtTokens.LT -> if (element.left.isZero()) element.right else null
+ KtTokens.GTEQ -> if (element.right.isOne()) element.left else null
+ KtTokens.LTEQ -> if (element.left.isOne()) element.right else null
+ else -> null
+}
+
+private fun KtBinaryExpression.isApplicable(analysisResult: AnalysisResult?): Boolean {
+ val targetExpression = getTargetExpression(this) ?: return false
+ val context = analysisResult?.bindingContext ?: return false
+
+ return targetExpression.isSizeOrLength(context)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/SpecifyTypeIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/SpecifyTypeIntention.kt
new file mode 100644
index 0000000..2e7b69a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/SpecifyTypeIntention.kt
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.types.ErrorUtils
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
+
+class SpecifyTypeIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private lateinit var displayString: String
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ val element = psi.getNonStrictParentOfType(KtCallableDeclaration::class.java) ?: return false
+
+ if (element.containingFile is KtCodeFragment) return false
+ if (element is KtFunctionLiteral) return false
+ if (element is KtConstructor<*>) return false
+ if (element.typeReference != null) return false
+
+ val initializer = (element as? KtDeclarationWithInitializer)?.initializer
+ if (initializer != null && initializer.textRange.containsOffset(caretOffset)) return false
+
+ if (element is KtNamedFunction && element.hasBlockBody()) return false
+
+ if (getTypeForDeclaration(element, analysisResult).isError) return false
+
+ displayString = if (element is KtFunction) "Specify return type explicitly" else "Specify type explicitly"
+
+ return true
+ }
+
+ override fun getDescription() = displayString
+
+ override fun implement() {
+ val element = psi.getNonStrictParentOfType(KtCallableDeclaration::class.java) ?: return
+ val type = getTypeForDeclaration(element, analysisResult)
+ val anchor = getAnchor(element) ?: return
+
+ addTypeAnnotation(anchor, type)
+ }
+
+ private fun addTypeAnnotation(element: PsiElement, type: KotlinType) {
+ val text = ": ${IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)}"
+
+ doc.insertString(element.textRange.endOffset, text, null)
+ }
+}
+
+fun getTypeForDeclaration(declaration: KtCallableDeclaration, analysisResult: AnalysisResult?): KotlinType {
+ val bindingContext = analysisResult?.bindingContext ?: return ErrorUtils.createErrorType("null type")
+
+ val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
+ val type = (descriptor as? CallableDescriptor)?.returnType
+ return type ?: ErrorUtils.createErrorType("null type")
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/SplitIfIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/SplitIfIntention.kt
new file mode 100644
index 0000000..e28f578
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/SplitIfIntention.kt
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.reformatting.format
+import org.jetbrains.kotlin.hints.atomicChange
+
+class SplitIfIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ return when (element) {
+ is KtOperationReferenceExpression -> isOperatorValid(element)
+ is KtIfExpression -> getFirstValidOperator(element) != null && element.ifKeyword.textRange.containsOffset(caretOffset)
+ else -> false
+ }
+ }
+
+ override fun getDescription() = "Split if into 2 if's"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val operator = when (element) {
+ is KtIfExpression -> getFirstValidOperator(element)!!
+ else -> element as KtOperationReferenceExpression
+ }
+
+ val ifExpression = operator.getNonStrictParentOfType(KtIfExpression::class.java) ?: return
+
+ val expression = operator.parent as KtBinaryExpression
+ val rightExpression = KtPsiUtil.safeDeparenthesize(getRight(expression, ifExpression.condition!!))
+ val leftExpression = KtPsiUtil.safeDeparenthesize(expression.left!!)
+ val thenBranch = ifExpression.then!!
+ val elseBranch = ifExpression.`else`
+
+ val newIf = with(StringBuilder()) {
+ when (operator.getReferencedNameElementType()) {
+ KtTokens.ANDAND -> {
+
+ append("if (").append(leftExpression.text).append(") {\n")
+ append("if (").append(rightExpression.text).append(") ")
+ append(thenBranch.text).append("\n}")
+ if (elseBranch != null) {
+ append("else ").append(elseBranch.text)
+ }
+ toString()
+ }
+ KtTokens.OROR -> {
+ append("if (").append(leftExpression.text).append(")").append(thenBranch.text)
+ append("else if (").append(rightExpression.text).append(") ")
+ append(thenBranch.text)
+ if (elseBranch != null) {
+ append("else ").append(elseBranch.text)
+ }
+ toString()
+ }
+ else -> throw IllegalArgumentException()
+ }
+ }
+
+ val startOffset = ifExpression.textRange.startOffset
+ val lengthToDelete = ifExpression.textLength
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, newIf, null)
+ format(this, element.textRange.startOffset)
+ }
+ }
+
+ private fun getRight(element: KtBinaryExpression, condition: KtExpression): KtExpression {
+ val conditionRange = condition.textRange
+ val startOffset = element.right!!.startOffset - conditionRange.startOffset
+ val endOffset = conditionRange.length
+ val rightString = condition.text.substring(startOffset, endOffset)
+
+ return KtPsiFactory(element).createExpression(rightString)
+ }
+
+ private fun getFirstValidOperator(element: KtIfExpression): KtOperationReferenceExpression? {
+ val condition = element.condition ?: return null
+ val children: Collection<KtOperationReferenceExpression> = PsiTreeUtil.findChildrenOfType(condition, KtOperationReferenceExpression::class.java)
+
+ return children.firstOrNull { isOperatorValid(it) }
+ }
+
+ private fun isOperatorValid(element: KtOperationReferenceExpression): Boolean {
+ val operator = element.getReferencedNameElementType()
+ if (operator != KtTokens.ANDAND && operator != KtTokens.OROR) return false
+
+ var expression = element.parent as? KtBinaryExpression ?: return false
+
+ if (expression.right == null || expression.left == null) return false
+
+ while (true) {
+ expression = expression.parent as? KtBinaryExpression ?: break
+ if (expression.operationToken != operator) return false
+ }
+
+ val ifExpression = expression.parent.parent as? KtIfExpression ?: return false
+
+ if (ifExpression.condition == null) return false
+ if (!PsiTreeUtil.isAncestor(ifExpression.condition, element, false)) return false
+
+ if (ifExpression.then == null) return false
+
+ return true
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ToInfixIntention.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ToInfixIntention.kt
new file mode 100644
index 0000000..afce868
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/intentions/ToInfixIntention.kt
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints.intentions
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import javax.swing.text.Document
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.hints.atomicChange
+
+class ToInfixIntention(doc: Document,
+ analysisResult: AnalysisResult?,
+ psi: PsiElement) : ApplicableIntention(doc, analysisResult, psi) {
+
+ private var expression: KtCallExpression? = null
+
+ override fun isApplicable(caretOffset: Int): Boolean {
+ expression = psi.getNonStrictParentOfType(KtCallExpression::class.java) ?: return false
+ val element = expression ?: return false
+
+ val calleeExpr = element.calleeExpression as? KtNameReferenceExpression ?: return false
+ if (!calleeExpr.textRange.containsOffset(caretOffset)) return false
+
+ val dotQualified = element.getQualifiedExpressionForSelector() ?: return false
+
+ if (element.typeArgumentList != null) return false
+
+ val argument = element.valueArguments.singleOrNull() ?: return false
+ if (argument.isNamed()) return false
+ if (argument.getArgumentExpression() == null) return false
+
+ val bindingContext = analysisResult?.bindingContext ?: return false
+ val resolvedCall = element.getResolvedCall(bindingContext) ?: return false
+ val function = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return false
+ if (!function.isInfix) return false
+
+ // check that receiver has type to filter out calls with package/java class qualifier
+ if (bindingContext.getType(dotQualified.receiverExpression) == null) return false
+
+ return true
+ }
+
+ override fun getDescription() = "Replace with infix function call"
+
+ override fun implement() {
+ val element = expression ?: return
+
+ val dotQualified = element.parent as KtDotQualifiedExpression
+ val receiver = dotQualified.receiverExpression
+ val argument = element.valueArguments.single().getArgumentExpression()!!
+ val name = element.calleeExpression!!.text
+
+ val newText = "${receiver.text} $name ${argument.text}"
+
+ val startOffset = receiver.textRange.startOffset
+ val lengthToDelete = element.textLength + receiver.textLength + 1
+
+ doc.atomicChange {
+ remove(startOffset, lengthToDelete)
+ insertString(startOffset, newText, null)
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/smartCastsChecker.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/smartCastsChecker.kt
new file mode 100644
index 0000000..dfd9500
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/hints/smartCastsChecker.kt
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.hints
+
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.renderer.DescriptorRenderer
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.netbeans.modules.csl.api.Hint
+import org.netbeans.modules.csl.api.HintSeverity
+import org.netbeans.modules.csl.api.OffsetRange
+
+fun getSmartCastHover(expression: KtSimpleNameExpression, parserResult: KotlinParserResult): Hint? {
+ val analysisResult = parserResult.analysisResult ?: return null
+ val bindingContext = analysisResult.analysisResult.bindingContext
+
+ val parentExpression = expression.parent
+
+ if (parentExpression is KtThisExpression || parentExpression is KtSuperExpression) return null
+
+ bindingContext[BindingContext.REFERENCE_TARGET, expression]?.let {
+ (it as? ConstructorDescriptor)?.containingDeclaration ?: it
+ } ?: return null
+
+ val smartCast = bindingContext.get(BindingContext.SMARTCAST, expression)
+
+ val description = smartCast?.defaultType?.let { "Smart cast to ${DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it)}" } ?: return null
+
+ return Hint(KotlinRule(HintSeverity.INFO),
+ description,
+ parserResult.snapshot.source.fileObject,
+ OffsetRange(expression.textRange.startOffset, expression.textRange.endOffset),
+ null,
+ 20
+ )
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indentation/KotlinIndentTask.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indentation/KotlinIndentTask.kt
new file mode 100644
index 0000000..e05fa6a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indentation/KotlinIndentTask.kt
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.indentation
+
+import org.jetbrains.kotlin.formatting.KotlinIndentStrategy
+import org.netbeans.modules.editor.indent.spi.Context
+import org.netbeans.modules.editor.indent.spi.IndentTask
+
+class KotlinIndentTask(val context: Context) : IndentTask {
+
+ override fun reindent() {
+ KotlinIndentStrategy(context).addIndent()
+ }
+
+ override fun indentLock() = null
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indentation/KotlinIndentTaskFactory.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indentation/KotlinIndentTaskFactory.java
new file mode 100644
index 0000000..9b057e7
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indentation/KotlinIndentTaskFactory.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.indentation;
+
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.modules.editor.indent.spi.Context;
+import org.netbeans.modules.editor.indent.spi.IndentTask;
+
+@MimeRegistration(mimeType="text/x-kt",service=IndentTask.Factory.class)
+public class KotlinIndentTaskFactory implements IndentTask.Factory {
+
+ @Override
+ public IndentTask createTask(Context context) {
+ return new KotlinIndentTask(context);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indexer/KotlinIndexer.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indexer/KotlinIndexer.java
new file mode 100644
index 0000000..f900ac9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indexer/KotlinIndexer.java
@@ -0,0 +1,36 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.indexer;
+
+import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.modules.parsing.spi.indexing.Context;
+import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexer;
+import org.netbeans.modules.parsing.spi.indexing.Indexable;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinIndexer extends EmbeddingIndexer {
+
+ @Override
+ protected void index(Indexable indexable, Parser.Result parserResult, Context context) {
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indexer/KotlinIndexerFactory.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indexer/KotlinIndexerFactory.kt
new file mode 100644
index 0000000..5f5cadc
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/indexer/KotlinIndexerFactory.kt
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.indexer
+
+import org.netbeans.modules.parsing.api.Snapshot
+import org.netbeans.modules.parsing.spi.indexing.Context
+import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory
+import org.netbeans.modules.parsing.spi.indexing.Indexable
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 9, 2016
+*/
+
+class KotlinIndexerFactory : EmbeddingIndexerFactory() {
+
+ override fun createIndexer(indexable: Indexable, snapshot: Snapshot) = KotlinIndexer()
+
+ override fun filesDeleted(deleted: Iterable<Indexable>, context: Context) {
+ }
+
+ override fun filesDirty(dirty: Iterable<Indexable>, context: Context) {
+ }
+
+ override fun getIndexerName() = "Kotlin Indexer"
+ override fun getIndexVersion() = 1
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/KotlinInstaller.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/KotlinInstaller.kt
new file mode 100644
index 0000000..095ca94
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/KotlinInstaller.kt
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.installer
+
+import org.jetbrains.kotlin.project.KotlinSources
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper
+import org.netbeans.modules.parsing.api.indexing.IndexingManager
+import org.openide.filesystems.FileObject
+import org.openide.loaders.DataObject
+import org.openide.windows.TopComponent
+import org.openide.windows.WindowManager
+import java.util.HashSet
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.isMavenProject
+import org.jetbrains.kotlin.projectsextensions.maven.MavenHelper
+
+class KotlinInstaller : Yenta() {
+
+ override fun friends() = setOf("org.netbeans.modules.maven",
+ "org.netbeans.modules.maven.embedder",
+ "org.netbeans.modules.jumpto",
+ "org.netbeans.modules.debugger.jpda",
+ "org.netbeans.modules.debugger.jpda.projects",
+ "org.netbeans.modules.java.api.common",
+ "org.netbeans.modules.java.preprocessorbridge"
+ )
+
+ override fun restored() {
+ WindowManager.getDefault().invokeWhenUIReady {
+ ProjectUtils.checkKtHome()
+ WindowManager.getDefault().registry.addPropertyChangeListener listener@{
+ if (it.propertyName == "opened") {
+ val newHashSet = it.newValue as HashSet<*>
+ val oldHashSet = it.oldValue as HashSet<*>
+ newHashSet.filter {!oldHashSet.contains(it)}
+ .forEach {
+ val dataObject = (it as? TopComponent)?.lookup?.lookup(DataObject::class.java) ?: return@forEach
+ val currentFile = dataObject.primaryFile
+ if (currentFile != null) {
+ if (currentFile.mimeType == "text/x-kt") {
+ checkUpdates()
+ checkProjectConfiguration(currentFile)
+ }
+ if (currentFile.mimeType == "text/x-java") {
+ checkVirtualSourceProvider(currentFile)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun checkVirtualSourceProvider(file: FileObject) {
+ val project = ProjectUtils.getKotlinProjectForFileObject(file) ?: return
+ if (!KotlinProjectHelper.hasJavaFiles(project)) {
+ KotlinProjectHelper.setHasJavaFiles(project)
+ KotlinSources(project).getAllKtFiles().forEach {
+ IndexingManager.getDefault().refreshAllIndices(it)
+ }
+ }
+ }
+
+ private fun checkProjectConfiguration(file: FileObject) {
+ val project = ProjectUtils.getKotlinProjectForFileObject(file) ?: return
+ if (project.isMavenProject()) MavenHelper.configure(project)
+ }
+
+ private fun checkUpdates() {
+ if (!KotlinUpdater.updated) KotlinUpdater.checkUpdates()
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/KotlinUpdater.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/KotlinUpdater.kt
new file mode 100644
index 0000000..4e85099
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/KotlinUpdater.kt
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.installer
+
+import java.io.IOException
+import java.net.HttpURLConnection
+import java.net.URL
+import org.jetbrains.kotlin.log.KotlinLogger
+import java.io.InputStream
+import java.io.BufferedInputStream
+import java.nio.charset.Charset
+import org.dom4j.io.SAXReader
+import java.io.StringReader
+import org.openide.NotifyDescriptor
+import org.openide.DialogDisplayer
+import java.net.URLEncoder
+import com.intellij.openapi.util.SystemInfo
+import java.util.Random
+import org.openide.modules.Modules
+import org.openide.util.NbPreferences
+
+object KotlinUpdater {
+
+ private val KOTLIN_PLUGIN_VERSION = "0.2.0"
+ private val USER_ID = "kotlin.userId"
+ private val pluginSite = "https://plugins.jetbrains.com/netbeans-plugins/kotlin/update?"
+
+ var updated = false
+ private set
+
+ @Synchronized fun checkUpdates() {
+ if (updated) return
+
+ val params = getRequestParams()
+ val url = URL("$pluginSite$params")
+
+ val connection = url.openConnection()
+ if (connection is HttpURLConnection) {
+ try {
+ connection.instanceFollowRedirects = false
+ connection.connect()
+ val responseCode = connection.responseCode
+
+ if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
+ val redirect = connection.getHeaderField("Location")
+ handleRedirect(redirect)
+ } else {
+ KotlinLogger.INSTANCE.logInfo("Response code: $responseCode")
+ }
+
+ } catch (e: IOException) {
+ KotlinLogger.INSTANCE.logInfo("Couldn't connect to $pluginSite")
+ } finally {
+ connection.disconnect()
+ }
+ }
+ }
+
+ private fun handleRedirect(redirect: String) {
+ KotlinLogger.INSTANCE.logInfo("Redirect: $redirect")
+ val url = URL("$redirect/version.xml")
+ val connection = url.openConnection()
+
+ if (connection is HttpURLConnection) {
+ try {
+ connection.connect()
+ val responseCode = connection.responseCode
+
+ if (responseCode == 200) {
+ updated = true
+
+ val latestVersion = getLatestVersion(connection.inputStream)
+ KotlinLogger.INSTANCE.logInfo("Latest version: $latestVersion. Installed version: $KOTLIN_PLUGIN_VERSION")
+
+ if (latestVersion != KOTLIN_PLUGIN_VERSION) {
+ showNotification(latestVersion)
+ }
+ }
+ } catch (e: IOException) {
+ KotlinLogger.INSTANCE.logInfo("Couldn't connect to $redirect")
+ } finally {
+ connection.disconnect()
+ }
+ }
+ }
+
+ private fun showNotification(latestVersion: String) {
+ val message = "A new version ($latestVersion) of the Kotlin plugin is available"
+ val notifyDescriptor = NotifyDescriptor.Message(message,
+ NotifyDescriptor.INFORMATION_MESSAGE)
+ DialogDisplayer.getDefault().notifyLater(notifyDescriptor)
+ }
+
+ private fun getLatestVersion(inputStream: InputStream): String {
+ val text = BufferedInputStream(inputStream).bufferedReader(Charset.defaultCharset()).readText()
+ val document = SAXReader().read(StringReader(text))
+
+ return document.rootElement.text
+ }
+
+ private fun getRequestParams(): String {
+ val os = URLEncoder.encode("${SystemInfo.OS_NAME} ${SystemInfo.OS_VERSION}", "UTF-8")
+ val userId = getUserID()
+ val netbeansVersion = getNetBeansVersion()
+
+ return "build=$netbeansVersion&pluginVersion=$KOTLIN_PLUGIN_VERSION&os=$os&uuid=$userId"
+ }
+
+ private fun getUserID(): Long {
+ val userId = NbPreferences.root().getLong(USER_ID, 0L)
+ if (userId == 0L) {
+ val generated = Math.abs(Random().nextLong())
+ NbPreferences.root().putLong(USER_ID, generated)
+ return generated
+ }
+
+ return userId
+ }
+
+ private fun getNetBeansVersion(): String {
+ val info = Modules.getDefault().ownerOf(Modules::class.java)
+
+ return info?.buildVersion ?: "-1"
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/Yenta.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/Yenta.java
new file mode 100644
index 0000000..f94a82a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/installer/Yenta.java
@@ -0,0 +1,175 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2012 Sun Microsystems, Inc.
+ */
+package org.jetbrains.kotlin.installer;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.openide.modules.Dependency;
+import org.openide.modules.ModuleInfo;
+import org.openide.modules.ModuleInstall;
+import org.openide.modules.Modules;
+
+/**
+ * Fixes up module system dependencies.
+ * <p>First add dependencies on whatever API modules you want to use, even if you are
+ * not (yet) their “friend”. Setting {@code <verifyRuntime>warn</verifyRuntime>} allows you
+ * to still compile against them and declare a regular specification version dependency,
+ * but be careful since this also disables checks about transitive dependency usage.
+ * <p>You can also add dependencies on modules with no exported packages; declare a
+ * specification version dependency and use the same flag to suppress checks.
+ * The same applies to modules exporting friend packages from which you also/instead
+ * want to use implementation packages. In either case be very
+ * careful and preferably catch {@link LinkageError} to be defensive.
+ * <p>Then add a module installer and extend this class rather than {@link ModuleInstall} directly.
+ * Override {@link #friends} and/or {@link #siblings}.
+ * When {@link #validate} is called, module system errors will be suppressed.
+ */
+public abstract class Yenta extends ModuleInstall {
+
+ /** Constructor for subclasses. */
+ protected Yenta() {}
+
+ /**
+ * Specifies the modules with whom you would like to be friends.
+ * These modules must be among your declared dependencies and they must export friend packages.
+ * For each such module, if you are not already a friend, you will be treated as one,
+ * so you will be able to access friend (but not private) packages.
+ * @return a set of module code name bases (default implementation is empty)
+ */
+ protected Set<String> friends() {
+ return Collections.emptySet();
+ }
+
+ /**
+ * Specifies the modules from whom you need complete access.
+ * These modules must be among your declared dependencies.
+ * For each such module, you will be able to access all packages, as with an implementation dependency.
+ * Be careful to defend against unexpected signature changes!
+ * @return a set of module code name bases (default implementation is empty)
+ */
+ protected Set<String> siblings() {
+ return Collections.emptySet();
+ }
+
+ /**
+ * @inheritDoc
+ * @throws IllegalStateException if {@link #friends} and {@link #siblings} are misconfigured or if the module system cannot be manipulated
+ */
+ @Override public void validate() throws IllegalStateException {
+ Set<String> friends = friends();
+ Set<String> siblings = siblings();
+ if (friends.isEmpty() && siblings.isEmpty()) {
+ throw new IllegalStateException("Must specify some friends and/or siblings");
+ }
+ ModuleInfo me = Modules.getDefault().ownerOf(getClass());
+ if (me == null) {
+ throw new IllegalStateException("No apparent module owning " + getClass());
+ }
+ try {
+ Object manager = me.getClass().getMethod("getManager").invoke(me);
+ for (String m : friends) {
+ if (siblings.contains(m)) {
+ throw new IllegalStateException("Cannot specify the same module " + m + " in both friends and siblings");
+ }
+ Object data = data(findDependency(manager, m));
+ Field friendNamesF = Class.forName("org.netbeans.ModuleData", true, data.getClass().getClassLoader()).getDeclaredField("friendNames");
+ friendNamesF.setAccessible(true);
+ Set<?> names = (Set<?>) friendNamesF.get(data);
+ Set<Object> newNames = new HashSet<Object>(names);
+ newNames.add(me.getCodeNameBase());
+ friendNamesF.set(data, newNames);
+ }
+ for (String m : siblings) {
+ ModuleInfo dep = findDependency(manager, m);
+ String implVersion = dep.getImplementationVersion();
+ if (implVersion == null) {
+ throw new IllegalStateException("No implementation version found in " + m);
+ }
+ Object data = data(me);
+ Field dependenciesF = Class.forName("org.netbeans.ModuleData", true, data.getClass().getClassLoader()).getDeclaredField("dependencies");
+ dependenciesF.setAccessible(true);
+ Dependency[] dependencies = (Dependency[]) dependenciesF.get(data);
+ boolean found = false;
+ for (int i = 0; i < dependencies.length; i++) {
+ if (dependencies[i].getName().replaceFirst("/.+$", "").equals(m)) {
+ Set<Dependency> nue = Dependency.create(Dependency.TYPE_MODULE, dependencies[i].getName() + " = " + implVersion);
+ if (nue.size() != 1) {
+ throw new IllegalStateException("Could not recreate dependency from " + dependencies[i] + " based on " + implVersion);
+ }
+ dependencies[i] = nue.iterator().next();
+ found = true;
+ }
+ }
+ if (!found) {
+ throw new IllegalStateException("Did not find dependency on " + m);
+ }
+ // StandardModule.classLoaderUp skips adding a parent if the dep seemed to offer us nothing, and this has already been called.
+ Object[] publicPackages = (Object[]) dep.getClass().getMethod("getPublicPackages").invoke(dep);
+ if (publicPackages != null && publicPackages.length == 0) {
+ me.getClassLoader().getClass().getMethod("append", ClassLoader[].class).invoke(me.getClassLoader(), (Object) new ClassLoader[] {dep.getClassLoader()});
+ }
+ }
+ } catch (IllegalStateException x) {
+ throw x;
+ } catch (Exception x) {
+ throw new IllegalStateException(x);
+ }
+ }
+
+ private ModuleInfo findDependency(/*ModuleManager*/Object manager, String m) throws Exception {
+ Object dep = manager.getClass().getMethod("get", String.class).invoke(manager, m);
+ if (dep == null) {
+ throw new IllegalStateException("No such dependency " + m);
+ }
+ return (ModuleInfo) dep;
+ }
+
+ private Object data(ModuleInfo module) throws Exception {
+ Method dataM = Class.forName("org.netbeans.Module", true, module.getClass().getClassLoader()).getDeclaredMethod("data");
+ dataM.setAccessible(true);
+ return dataM.invoke(module);
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/j2k/ConvertToKotlinAction.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/j2k/ConvertToKotlinAction.java
new file mode 100644
index 0000000..9a3776b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/j2k/ConvertToKotlinAction.java
@@ -0,0 +1,81 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.j2k;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import javax.swing.text.Document;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.api.project.Project;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.loaders.DataObject;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle.Messages;
+
+@ActionID(
+ category = "Refactoring",
+ id = "org.jetbrains.kotlin.j2k.ConvertToKotlinAction"
+)
+@ActionRegistration(
+ iconBase = "org/jetbrains/kotlin/kotlin.png",
+ displayName = "#CTL_ConvertToKotlinAction"
+)
+@ActionReference(path = "Loaders/text/x-java/Actions", position = 2050)
+@Messages("CTL_ConvertToKotlinAction=Convert to Kotlin")
+public final class ConvertToKotlinAction implements ActionListener {
+
+ private final DataObject context;
+
+ public ConvertToKotlinAction(DataObject context) {
+ this.context = context;
+ }
+
+ private void showDialog(FileObject fo, Document doc, Project project) {
+ NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
+ "Convert to Kotlin. Do you want to continue?",
+ NotifyDescriptor.YES_NO_OPTION);
+ Object result = DialogDisplayer.getDefault().notify(nd);
+ if (result == NotifyDescriptor.YES_OPTION) {
+ Java2KotlinConverter.convert(doc, project, fo);
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent ev) {
+ FileObject fo = context.getPrimaryFile();
+ try {
+ Document doc = ProjectUtils.getDocumentFromFileObject(fo);
+ if (doc == null) {
+ return;
+ }
+ Project project = ProjectUtils.getKotlinProjectForFileObject(fo);
+ if (project == null) {
+ return;
+ }
+
+ showDialog(fo, doc, project);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/j2k/Java2KotlinConverter.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/j2k/Java2KotlinConverter.java
new file mode 100644
index 0000000..34473d5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/j2k/Java2KotlinConverter.java
@@ -0,0 +1,122 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.j2k;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.jetbrains.kotlin.model.KotlinEnvironment;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.api.project.Project;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.cookies.OpenCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.jetbrains.kotlin.reformatting.FormatUtilsKt;
+import org.openide.loaders.DataObject;
+import org.openide.util.Exceptions;
+
+public class Java2KotlinConverter {
+
+ public static void convert(Document doc, Project proj, FileObject fo) {
+ String translatedCode = getTranslatedCode(doc, proj);
+ if (translatedCode == null) {
+ showError("Error while converting to Kotlin");
+ return;
+ }
+
+ String newKotlinFilePath = fo.getParent().getPath() +
+ ProjectUtils.FILE_SEPARATOR + fo.getName() + ".kt";
+
+ File kotlinFile = new File(newKotlinFilePath);
+ if (kotlinFile.exists()) {
+ showError(newKotlinFilePath + " already exists");
+ return;
+ }
+
+ try {
+ kotlinFile.createNewFile();
+ } catch (IOException ex) {
+ showError("Error");
+ return;
+ }
+
+ if (!addContent(kotlinFile, translatedCode)) {
+ showError("Couldn't add content to Kotlin file");
+ return;
+ }
+
+ try {
+ fo.delete();
+ } catch (IOException ex) {
+ showError("Couldn't delete Java file");
+ return;
+ }
+
+ FileObject kotlinFO = FileUtil.toFileObject(kotlinFile);
+
+ try {
+ Document document = ProjectUtils.getDocumentFromFileObject(kotlinFO);
+ FormatUtilsKt.format(document, 0, proj);
+
+ DataObject.find(kotlinFO).getLookup().lookup(OpenCookie.class).open();
+ } catch (Exception ex) {
+ KotlinLogger.INSTANCE.logException("Cannot open Kotlin file", ex);
+ }
+ }
+
+ private static boolean addContent(File file, String code) {
+ BufferedWriter writer = null;
+ try {
+ writer = Files.newBufferedWriter(file.toPath());
+ writer.write(code);
+ writer.flush();
+ return true;
+ } catch (IOException ex) {
+ return false;
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ }
+
+ private static void showError(String message) {
+ NotifyDescriptor nd = new NotifyDescriptor.Message(message, NotifyDescriptor.ERROR_MESSAGE);
+ DialogDisplayer.getDefault().notifyLater(nd);
+ }
+
+ private static String getTranslatedCode(Document doc, Project proj) {
+ try {
+ String contents = doc.getText(0, doc.getLength());
+ return JavaToKotlinTranslatorKt.translateToKotlin(contents,
+ KotlinEnvironment.Companion.getEnvironment(proj).getProject());
+ } catch (BadLocationException ex) {
+ return null;
+ }
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/KotlinLanguage.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/KotlinLanguage.java
new file mode 100644
index 0000000..eb8d96a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/KotlinLanguage.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.language;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.kotlin.completion.KotlinCodeCompletionHandler;
+import org.jetbrains.kotlin.structurescanner.KotlinStructureScanner;
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser;
+import org.jetbrains.kotlin.diagnostics.netbeans.textinterceptor.KotlinKeystrokeHandler;
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinTokenId;
+import org.jetbrains.kotlin.highlighter.occurrences.KotlinOccurrencesFinder;
+import org.jetbrains.kotlin.highlighter.semanticanalyzer.KotlinSemanticAnalyzer;
+import org.jetbrains.kotlin.hints.KotlinHintsProvider;
+import org.jetbrains.kotlin.indexer.KotlinIndexerFactory;
+import org.jetbrains.kotlin.refactorings.rename.KotlinInstantRenamer;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.modules.csl.api.CodeCompletionHandler;
+import org.netbeans.modules.csl.api.HintsProvider;
+import org.netbeans.modules.csl.api.InstantRenamer;
+import org.netbeans.modules.csl.api.KeystrokeHandler;
+import org.netbeans.modules.csl.api.OccurrencesFinder;
+import org.netbeans.modules.csl.api.SemanticAnalyzer;
+import org.netbeans.modules.csl.api.StructureScanner;
+import org.netbeans.modules.csl.spi.DefaultLanguageConfig;
+import org.netbeans.modules.csl.spi.LanguageRegistration;
+import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.modules.parsing.spi.indexing.EmbeddingIndexerFactory;
+
+@LanguageRegistration(mimeType = "text/x-kt")
+public class KotlinLanguage extends DefaultLanguageConfig {
+
+ @NotNull
+ @Override
+ public Language getLexerLanguage() {
+ return KotlinTokenId.Companion.getLanguage();
+ }
+
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return "KT";
+ }
+
+ @Override
+ public Parser getParser(){
+ return new KotlinParser();
+ }
+
+ @Override
+ public String getLineCommentPrefix() {
+ return "//";
+ }
+
+ @Override
+ public SemanticAnalyzer getSemanticAnalyzer() {
+ return new KotlinSemanticAnalyzer();
+ }
+
+ @Override
+ public boolean hasStructureScanner(){
+ return true;
+ }
+
+ @Override
+ public StructureScanner getStructureScanner(){
+ return new KotlinStructureScanner();
+ }
+
+ @Override
+ public boolean hasHintsProvider() {
+ return true;
+ }
+
+ @Override
+ public HintsProvider getHintsProvider() {
+ return new KotlinHintsProvider();
+ }
+
+ @Override
+ public boolean hasOccurrencesFinder() {
+ return true;
+ }
+
+ @Override
+ public OccurrencesFinder getOccurrencesFinder() {
+ return new KotlinOccurrencesFinder();
+ }
+
+ @Override
+ public CodeCompletionHandler getCompletionHandler() {
+ return new KotlinCodeCompletionHandler();
+ }
+
+ @Override
+ public InstantRenamer getInstantRenamer() {
+ return new KotlinInstantRenamer();
+ }
+
+ @Override
+ public EmbeddingIndexerFactory getIndexerFactory() {
+ return new KotlinIndexerFactory();
+ }
+
+ @Override
+ public KeystrokeHandler getKeystrokeHandler() {
+ return new KotlinKeystrokeHandler();
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/KotlinLanguageHierarchy.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/KotlinLanguageHierarchy.kt
new file mode 100644
index 0000000..6ede6a0
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/KotlinLanguageHierarchy.kt
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.language
+
+import org.netbeans.spi.lexer.LanguageHierarchy
+import org.netbeans.spi.lexer.LexerRestartInfo
+import org.jetbrains.kotlin.highlighter.TokenType
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinLexerProxy
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinTokenId
+
+class KotlinLanguageHierarchy : LanguageHierarchy<KotlinTokenId>() {
+
+ companion object {
+ private val tokens = listOf(
+ KotlinTokenId(TokenType.KEYWORD.name, TokenType.KEYWORD.name, 0),
+ KotlinTokenId(TokenType.IDENTIFIER.name, TokenType.IDENTIFIER.name, 1),
+ KotlinTokenId(TokenType.STRING.name,TokenType.STRING.name,2),
+ KotlinTokenId(TokenType.SINGLE_LINE_COMMENT.name,TokenType.SINGLE_LINE_COMMENT.name,3),
+ KotlinTokenId(TokenType.MULTI_LINE_COMMENT.name,TokenType.MULTI_LINE_COMMENT.name,4),
+ KotlinTokenId(TokenType.KDOC_TAG_NAME.name,TokenType.KDOC_TAG_NAME.name,5),
+ KotlinTokenId(TokenType.WHITESPACE.name,TokenType.WHITESPACE.name,6),
+ KotlinTokenId(TokenType.UNDEFINED.name,TokenType.UNDEFINED.name,7),
+ KotlinTokenId(TokenType.ANNOTATION.name,TokenType.ANNOTATION.name,8),
+ KotlinTokenId(TokenType.KDOC_LINK.name,TokenType.KDOC_LINK.name,9)
+ )
+
+ fun getToken(id: Int) = tokens.first { it.ordinal() == id }
+ }
+
+ override fun createTokenIds() = tokens
+ override fun createLexer(info: LexerRestartInfo<KotlinTokenId>) = KotlinLexerProxy(info)
+ override fun mimeType() = "text/x-kt"
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/priorities.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/priorities.kt
new file mode 100644
index 0000000..193c4b8
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/language/priorities.kt
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.language
+
+object Priorities {
+ val HINT_PRIORITY = 10
+ val SEMANTIC_ANALYZER_PRIORITY = 999
+ val OCCURRENCES_FINDER_PRIORITY = 1000
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/log/KotlinLogger.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/log/KotlinLogger.java
new file mode 100644
index 0000000..db9bede
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/log/KotlinLogger.java
@@ -0,0 +1,55 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.log;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import org.openide.util.Exceptions;
+
+
+public class KotlinLogger {
+
+ public final static KotlinLogger INSTANCE = new KotlinLogger();
+ private final static Logger LOGGER =
+ Logger.getLogger(KotlinLogger.class.getName());
+
+ private KotlinLogger() {
+ System.setProperty(KotlinLogger.class.getName(), "100");
+ try {
+ LogManager.getLogManager().readConfiguration();
+ } catch (IOException | SecurityException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ public void logException(String message, Throwable thrown) {
+ LOGGER.log(Level.SEVERE, message, thrown);
+ }
+
+ public void logWarning(String message) {
+ LOGGER.warning(message);
+ }
+
+ public void logInfo(String message) {
+ LOGGER.log(Level.INFO, message);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinEnvironment.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinEnvironment.kt
new file mode 100644
index 0000000..623060a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinEnvironment.kt
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.model
+
+import com.intellij.codeInsight.ExternalAnnotationsManager
+import com.intellij.codeInsight.InferredAnnotationsManager
+import org.jetbrains.kotlin.resolve.lang.kotlin.NetBeansVirtualFileFinderFactory
+import java.io.File
+import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
+import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
+import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
+import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
+import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
+import org.jetbrains.kotlin.parsing.KotlinParserDefinition
+import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
+import com.intellij.codeInsight.ContainerProvider
+import com.intellij.codeInsight.NullableNotNullManager
+import com.intellij.codeInsight.runner.JavaMainMethodProvider
+import com.intellij.core.CoreApplicationEnvironment
+import com.intellij.core.CoreJavaFileManager
+import com.intellij.core.JavaCoreApplicationEnvironment
+import com.intellij.core.JavaCoreProjectEnvironment
+import com.intellij.mock.MockProject
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.components.ServiceManager
+import com.intellij.openapi.extensions.ExtensionPointName
+import com.intellij.openapi.extensions.Extensions
+import com.intellij.openapi.extensions.ExtensionsArea
+import com.intellij.openapi.fileTypes.PlainTextFileType
+import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.PsiElementFinder
+import com.intellij.psi.PsiManager
+import com.intellij.psi.augment.PsiAugmentProvider
+import com.intellij.psi.codeStyle.CodeStyleSettingsProvider
+import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider
+import com.intellij.psi.compiled.ClassFileDecompilers
+import com.intellij.psi.impl.PsiTreeChangePreprocessor
+import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy
+import com.intellij.psi.impl.file.impl.JavaFileManager
+import org.jetbrains.kotlin.filesystem.KotlinLightClassManager
+import org.jetbrains.kotlin.resolve.BuiltInsReferenceResolver
+import org.jetbrains.kotlin.resolve.KotlinCacheServiceImpl
+import org.jetbrains.kotlin.resolve.KotlinSourceIndex
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.utils.KotlinImportInserterHelper
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
+import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
+import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
+import com.intellij.formatting.KotlinLanguageCodeStyleSettingsProvider
+import com.intellij.formatting.KotlinSettingsProvider
+import java.net.URLDecoder
+import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
+import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndexImpl
+import org.jetbrains.kotlin.cli.jvm.compiler.MockExternalAnnotationsManager
+import org.jetbrains.kotlin.cli.jvm.compiler.MockInferredAnnotationsManager
+import org.jetbrains.kotlin.idea.KotlinFileType
+import org.jetbrains.kotlin.config.CommonConfigurationKeys
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.idea.util.ImportInsertHelper
+import org.jetbrains.kotlin.js.resolve.diagnostics.DefaultErrorMessagesJs
+import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinderFactory
+import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor
+import org.jetbrains.kotlin.resolve.diagnostics.SuppressStringProvider
+import org.jetbrains.kotlin.resolve.jvm.diagnostics.DefaultErrorMessagesJvm
+import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
+import org.jetbrains.kotlin.script.KotlinScriptDefinitionProvider
+import org.jetbrains.kotlin.script.KotlinScriptExternalImportsProvider
+import org.netbeans.api.project.Project as NBProject
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl
+import com.intellij.openapi.util.SystemInfo
+
+//copied from kotlin eclipse plugin to avoid RuntimeException: Could not find installation home path.
+//Please make sure bin/idea.properties is present in the installation directory
+private fun setIdeaIoUseFallback() {
+ if (SystemInfo.isWindows) {
+ val properties = System.getProperties()
+
+ properties.setProperty("idea.io.use.nio2", java.lang.Boolean.TRUE.toString())
+
+ if (!(SystemInfo.isJavaVersionAtLeast("1.7") && "1.7.0-ea" != SystemInfo.JAVA_VERSION)) {
+ properties.setProperty("idea.io.use.fallback", java.lang.Boolean.TRUE.toString())
+ }
+ }
+}
+
+class KotlinEnvironment private constructor(kotlinProject: NBProject, disposable: Disposable) {
+
+ companion object {
+ val CACHED_ENVIRONMENT = hashMapOf<NBProject, KotlinEnvironment>()
+
+ @Synchronized fun getEnvironment(kotlinProject: NBProject): KotlinEnvironment {
+ if (!CACHED_ENVIRONMENT.containsKey(kotlinProject)) {
+ CACHED_ENVIRONMENT.put(kotlinProject, KotlinEnvironment(kotlinProject, Disposer.newDisposable()))
+ }
+
+ return CACHED_ENVIRONMENT[kotlinProject]!!
+ }
+
+ @Synchronized fun updateKotlinEnvironment(kotlinProject: NBProject) = getEnvironment(kotlinProject).configureClasspath(kotlinProject)
+ }
+
+ val applicationEnvironment: JavaCoreApplicationEnvironment
+ private val projectEnvironment: JavaCoreProjectEnvironment
+ val project: MockProject
+ val roots = hashSetOf<JavaRoot>()
+
+ val index by lazy { JvmDependenciesIndexImpl(roots.toList()) }
+
+ val configuration = CompilerConfiguration()
+
+ init {
+ val startTime = System.nanoTime()
+
+ setIdeaIoUseFallback()
+
+ applicationEnvironment = createJavaCoreApplicationEnvironment(disposable)
+ projectEnvironment = object : JavaCoreProjectEnvironment(disposable, applicationEnvironment) {
+ override fun preregisterServices() {
+ registerProjectExtensionPoints(Extensions.getArea(project))
+ }
+
+ override fun createCoreFileManager() = KotlinCliJavaFileManagerImpl(PsiManager.getInstance(project))
+ }
+ project = projectEnvironment.project
+
+ with (project) {
+ val scriptDefinitionProvider = KotlinScriptDefinitionProvider()
+ registerService(KotlinScriptDefinitionProvider::class.java, scriptDefinitionProvider)
+ registerService(
+ KotlinScriptExternalImportsProvider::class.java,
+ KotlinScriptExternalImportsProvider(project, scriptDefinitionProvider))
+
+ registerService(ModuleVisibilityManager::class.java, CliModuleVisibilityManagerImpl())
+ registerService(NullableNotNullManager::class.java, KotlinNullableNotNullManager(kotlinProject))
+ registerService(CoreJavaFileManager::class.java,
+ ServiceManager.getService(project, JavaFileManager::class.java) as CoreJavaFileManager)
+
+ val cliLightClassGenerationSupport = CliLightClassGenerationSupport(project)
+ registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
+ registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
+ registerService(CodeAnalyzerInitializer::class.java, cliLightClassGenerationSupport)
+
+ registerService(KtLightClassForFacade.FacadeStubCache::class.java, KtLightClassForFacade.FacadeStubCache(project))
+ registerService(KotlinLightClassManager::class.java, KotlinLightClassManager(kotlinProject))
+ registerService(BuiltInsReferenceResolver::class.java, BuiltInsReferenceResolver(project))
+ registerService(KotlinSourceIndex::class.java, KotlinSourceIndex())
+ registerService(KotlinCacheService::class.java, KotlinCacheServiceImpl(project, kotlinProject))
+ registerService(JvmVirtualFileFinderFactory::class.java, NetBeansVirtualFileFinderFactory(kotlinProject))
+ registerService(ImportInsertHelper::class.java, KotlinImportInserterHelper())
+
+ registerService(ExternalAnnotationsManager::class.java, MockExternalAnnotationsManager())
+ registerService(InferredAnnotationsManager::class.java, MockInferredAnnotationsManager())
+ }
+
+ configuration.put<String>(CommonConfigurationKeys.MODULE_NAME, project.name)
+
+ configureClasspath(kotlinProject)
+
+ ExpressionCodegenExtension.Companion.registerExtensionPoint(project)
+
+ getExtensionsFromCommonXml()
+ getExtensionsFromKotlin2JvmXml()
+
+ CACHED_ENVIRONMENT.put(kotlinProject, this)
+ KotlinLogger.INSTANCE.logInfo("KotlinEnvironment init: ${(System.nanoTime() - startTime)} ns")
+ }
+
+ private fun registerProjectExtensionPoints(area: ExtensionsArea) {
+ CoreApplicationEnvironment.registerExtensionPoint(area,
+ PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class.java)
+ CoreApplicationEnvironment.registerExtensionPoint(area,
+ PsiElementFinder.EP_NAME, PsiElementFinder::class.java)
+ }
+
+ private fun getExtensionsFromCommonXml() {
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ExtensionPointName("org.jetbrains.kotlin.diagnosticSuppressor"), DiagnosticSuppressor::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ExtensionPointName("org.jetbrains.kotlin.defaultErrorMessages"), DefaultErrorMessages.Extension::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ExtensionPointName("org.jetbrains.kotlin.suppressStringProvider"), SuppressStringProvider::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ExtensionPointName(("org.jetbrains.kotlin.expressionCodegenExtension")), ExpressionCodegenExtension::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ExtensionPointName(("org.jetbrains.kotlin.classBuilderFactoryInterceptorExtension")), ClassBuilderInterceptorExtension::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ExtensionPointName(("org.jetbrains.kotlin.packageFragmentProviderExtension")), PackageFragmentProviderExtension::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(CodeStyleSettingsProvider.EXTENSION_POINT_NAME, KotlinSettingsProvider::class.java)
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(LanguageCodeStyleSettingsProvider.EP_NAME, KotlinLanguageCodeStyleSettingsProvider::class.java)
+
+ with (Extensions.getRootArea()) {
+ getExtensionPoint(CodeStyleSettingsProvider.EXTENSION_POINT_NAME).registerExtension(KotlinSettingsProvider())
+ getExtensionPoint(LanguageCodeStyleSettingsProvider.EP_NAME).registerExtension(KotlinLanguageCodeStyleSettingsProvider())
+ getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesJvm())
+ getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesJs())
+ }
+ }
+
+ private fun getExtensionsFromKotlin2JvmXml() {
+ CoreApplicationEnvironment.registerComponentInstance<DefaultErrorMessages.Extension>(Extensions.getRootArea().picoContainer,
+ DefaultErrorMessages.Extension::class.java, DefaultErrorMessagesJvm())
+ }
+
+ fun configureClasspath(kotlinProject: NBProject) {
+ val classpath = ProjectUtils.getClasspath(kotlinProject)
+ KotlinLogger.INSTANCE.logInfo("Project ${kotlinProject.projectDirectory.path} classpath is $classpath")
+ classpath.forEach {
+ if (it.endsWith("!/")) {
+ addToClasspath(it.split("!/")[0].substringAfter("file:"), null)
+ } else {
+ addToClasspath(it, null)
+ }
+ }
+ }
+
+ private fun createJavaCoreApplicationEnvironment(disposable: Disposable): JavaCoreApplicationEnvironment {
+ Extensions.cleanRootArea(disposable)
+ registerAppExtensionPoints()
+ val javaApplicationEnvironment = JavaCoreApplicationEnvironment(disposable)
+
+ with (javaApplicationEnvironment) {
+ registerFileType(PlainTextFileType.INSTANCE, "xml")
+ registerFileType(KotlinFileType.INSTANCE, "kt")
+ registerParserDefinition(KotlinParserDefinition())
+ application.registerService(KotlinBinaryClassCache::class.java, KotlinBinaryClassCache())
+ }
+
+ return javaApplicationEnvironment
+ }
+
+ private fun registerAppExtensionPoints() {
+ CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ContainerProvider.EP_NAME,
+ ContainerProvider::class.java)
+ CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ClsCustomNavigationPolicy.EP_NAME,
+ ClsCustomNavigationPolicy::class.java)
+ CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ClassFileDecompilers.EP_NAME,
+ ClassFileDecompilers.Decompiler::class.java)
+
+ CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class.java)
+ CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class.java)
+ }
+
+ private fun addToClasspath(path: String, rootType: JavaRoot.RootType?) {
+ val file = File(path)
+ if (file.isFile) {
+ val jarFile = applicationEnvironment.jarFileSystem.findFileByPath("$path!/") ?: return
+ projectEnvironment.addJarToClassPath(file)
+ val type = rootType ?: JavaRoot.RootType.BINARY
+
+ roots.add(JavaRoot(jarFile, type, null))
+ } else {
+ val root = applicationEnvironment.localFileSystem.findFileByPath(path) ?: return
+ projectEnvironment.addSourcesToClasspath(root)
+ val type = rootType ?: JavaRoot.RootType.SOURCE
+
+ roots.add(JavaRoot(root, type, null))
+ }
+ }
+
+ fun getVirtualFile(location: String) = applicationEnvironment.localFileSystem.findFileByPath(location)
+
+ fun getVirtualFileInJar(pathToJar: String, relativePath: String): VirtualFile? {
+ val decodedPathToJar = URLDecoder.decode(pathToJar, "UTF-8") ?: pathToJar
+ val decodedRelativePath = URLDecoder.decode(relativePath, "UTF-8") ?: relativePath
+
+ return applicationEnvironment.jarFileSystem.findFileByPath("$decodedPathToJar!/$decodedRelativePath")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinLightVirtualFile.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinLightVirtualFile.kt
new file mode 100644
index 0000000..62c8d2d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinLightVirtualFile.kt
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.model
+
+import com.intellij.testFramework.LightVirtualFile
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.openide.filesystems.FileObject
+
+class KotlinLightVirtualFile(val fo: FileObject, text: String) :
+ LightVirtualFile(fo.name, KotlinLanguage.INSTANCE, text) {
+
+ override fun getPath(): String = fo.path
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinNullableNotNullManager.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinNullableNotNullManager.kt
new file mode 100644
index 0000000..bc3187a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/model/KotlinNullableNotNullManager.kt
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.model
+
+import com.intellij.codeInsight.NullableNotNullManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiModifierListOwner
+import org.netbeans.api.project.Project
+
+class KotlinNullableNotNullManager(private val javaProject: Project) : NullableNotNullManager() {
+
+ init {
+ setNotNulls("NotNull")
+ setNullables("Nullable")
+ }
+
+ override fun hasHardcodedContracts(element: PsiElement) = false
+
+ override fun isNotNull(owner: PsiModifierListOwner, checkBases: Boolean): Boolean {
+ val notNullAnnotations = notNulls.toSet()
+ return owner.modifierList?.annotations?.any { annotation ->
+ annotation.qualifiedName in notNullAnnotations
+ } ?: false
+ }
+
+ override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/jarNavigationUtil.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/jarNavigationUtil.kt
new file mode 100644
index 0000000..132e889
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/jarNavigationUtil.kt
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation
+
+import java.io.File
+import org.openide.filesystems.FileObject
+import org.openide.filesystems.FileUtil
+
+fun getFileObjectFromJar(path: String): FileObject? {
+ val pathParts = getJarAndInternalPaths(path) ?: return null
+
+ val jar = File(pathParts.first).absoluteFile
+
+ var fileObject = FileUtil.toFileObject(jar) ?: return null
+ fileObject = FileUtil.getArchiveRoot(fileObject) ?: return null
+
+ val internalPathParts = pathParts.second.split("/")
+ for (pathPart in internalPathParts) {
+ fileObject = fileObject.getFileObject(pathPart) ?: return null
+ }
+
+ return fileObject
+}
+
+private fun getJarAndInternalPaths(path: String): Pair<String, String>? {
+ val separator = "!/"
+ val pathParts = path.split(separator)
+ if (pathParts.size < 2) {
+ return null
+ }
+ return Pair(pathParts[0], pathParts[1])
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/navigationUtil.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/navigationUtil.kt
new file mode 100644
index 0000000..1da406b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/navigationUtil.kt
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation
+
+import com.intellij.psi.PsiElement
+import javax.swing.text.Document
+import org.jetbrains.kotlin.utils.LineEndUtil
+import org.jetbrains.kotlin.utils.ProjectUtils
+
+fun getReferenceExpression(doc: Document, offset: Int): PsiElement? {
+ val fo = ProjectUtils.getFileObjectForDocument(doc) ?: return null
+ val ktFile = ProjectUtils.getKtFile(doc.getText(0, doc.length), fo)
+
+ val documentOffset = LineEndUtil.convertCrToDocumentOffset(ktFile.text, offset)
+ return ktFile.findElementAt(documentOffset)
+}
+
+fun getSpan(expression: PsiElement?): Pair<Int, Int>? {
+ expression ?: return null
+
+ val start = expression.textRange.startOffset
+ val end = expression.textRange.endOffset
+
+ return Pair(start, end)
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/JavaHyperlinkProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/JavaHyperlinkProvider.java
new file mode 100644
index 0000000..bdd38cd
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/JavaHyperlinkProvider.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation.netbeans;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.EnumSet;
+import java.util.Set;
+import javax.swing.text.Document;
+import javax.swing.text.StyledDocument;
+import kotlin.Pair;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.project.Project;
+import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProviderExt;
+import org.netbeans.lib.editor.hyperlink.spi.HyperlinkType;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+
+@MimeRegistration(mimeType = "text/x-java", service = HyperlinkProviderExt.class)
+public final class JavaHyperlinkProvider implements HyperlinkProviderExt {
+
+ private Class clazz = null;
+ private Object object = null;
+
+ public JavaHyperlinkProvider() {
+ ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class);
+ try {
+ clazz = Class.forName(
+ "org.netbeans.modules.java.editor.hyperlink.JavaHyperlinkProvider",
+ true, loader);
+ Constructor constructor = clazz.getConstructor();
+ object = constructor.newInstance();
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ @Override
+ public Set<HyperlinkType> getSupportedHyperlinkTypes() {
+ return EnumSet.of(HyperlinkType.GO_TO_DECLARATION, HyperlinkType.ALT_HYPERLINK);
+ }
+
+ private int[] getIdentifierSpan(Document doc, int offset) {
+ if (clazz == null || object == null) {
+ return new int[0];
+ }
+
+ try {
+ Method method = clazz.getMethod("getHyperlinkSpan", Document.class, int.class, HyperlinkType.class);
+ return (int[]) method.invoke(object, doc, offset, null);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return new int[0];
+ }
+
+ private String tooltipText(Document doc, int offset) {
+ if (clazz == null || object == null) {
+ return null;
+ }
+
+ try {
+ Method method = clazz.getMethod("getTooltipText", Document.class, int.class, HyperlinkType.class);
+ return (String) method.invoke(object, doc, offset, null);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return null;
+ }
+
+ private void clickAction(Document doc, int offset, HyperlinkType type) {
+ if (clazz == null || object == null) {
+ return;
+ }
+
+ try {
+ Method method = clazz.getMethod("performClickAction", Document.class, int.class, HyperlinkType.class);
+ method.invoke(object, doc, offset, type);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ @Override
+ public boolean isHyperlinkPoint(Document doc, int offset, HyperlinkType type) {
+ return getHyperlinkSpan(doc, offset, type) != null;
+ }
+
+ @Override
+ public int[] getHyperlinkSpan(Document doc, int offset, HyperlinkType type) {
+ return getIdentifierSpan(doc, offset);
+ }
+
+ @Override
+ public void performClickAction(Document doc, int offset, HyperlinkType type) {
+ switch (type) {
+ case GO_TO_DECLARATION:
+ ElementHandle element = FromJavaToKotlinNavigationUtilsKt.getElement(doc, offset);
+ FileObject file = ProjectUtils.getFileObjectForDocument(doc);
+ Project project = ProjectUtils.getKotlinProjectForFileObject(file);
+ Pair<KtFile, Integer> pair = FromJavaToKotlinNavigationUtilsKt.findKotlinFileToNavigate(element, project, doc);
+
+ if (pair == null) {
+ clickAction(doc, offset, type);
+ break;
+ }
+
+ KtFile ktFile = pair.getFirst();
+ int offsetToOpen = pair.getSecond();
+
+ if (ktFile != null) {
+ String filePath = ktFile.getVirtualFile().getPath();
+ FileObject fileToOpen = FileUtil.toFileObject(new File(filePath));
+ try {
+ StyledDocument docToOpen = ProjectUtils.getDocumentFromFileObject(fileToOpen);
+ if (docToOpen == null) return;
+ OpenDeclarationKt.openFileAtOffset(docToOpen, offsetToOpen);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ } else clickAction(doc, offset, type);
+ break;
+ case ALT_HYPERLINK:
+ clickAction(doc, offset, type);
+ break;
+ }
+ }
+
+ @Override
+ public String getTooltipText(Document doc, int offset, HyperlinkType type) {
+ return tooltipText(doc, offset);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/KotlinHyperlinkProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/KotlinHyperlinkProvider.java
new file mode 100644
index 0000000..5479ac8
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/KotlinHyperlinkProvider.java
@@ -0,0 +1,106 @@
+/*
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.navigation.netbeans;
+
+import com.google.common.collect.Sets;
+import com.intellij.psi.PsiElement;
+import java.util.Set;
+import javax.swing.text.Document;
+import kotlin.Pair;
+import org.jetbrains.kotlin.navigation.NavigationUtilKt;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.jetbrains.kotlin.psi.KtReferenceExpression;
+import org.jetbrains.kotlin.navigation.references.ReferenceUtilsKt;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.api.project.Project;
+import org.netbeans.lib.editor.hyperlink.spi.HyperlinkProviderExt;
+import org.netbeans.lib.editor.hyperlink.spi.HyperlinkType;
+import org.openide.filesystems.FileObject;
+
+@MimeRegistration(mimeType = "text/x-kt", service = HyperlinkProviderExt.class)
+public class KotlinHyperlinkProvider implements HyperlinkProviderExt {
+
+ private PsiElement psi = null;
+ private KtReferenceExpression referenceExpression = null;
+ private Pair<Document, Integer> navigationCache = null;
+
+ @Override
+ public boolean isHyperlinkPoint(Document doc, int offset, HyperlinkType type) {
+ psi = NavigationUtilKt.getReferenceExpression(doc, offset);
+ if (psi == null) return false;
+
+ referenceExpression = ReferenceUtilsKt.getReferenceExpression(psi);
+ return referenceExpression != null;
+
+ }
+
+ @Override
+ public int[] getHyperlinkSpan(Document doc, int offset, HyperlinkType type) {
+ if (isHyperlinkPoint(doc, offset, type)) {
+ Pair<Integer, Integer> span = NavigationUtilKt.getSpan(psi);
+ if (span == null) {
+ return null;
+ }
+ return new int[]{span.getFirst(), span.getSecond()};
+ }
+ return null;
+ }
+
+ @Override
+ public void performClickAction(Document doc, int offset, HyperlinkType type) {
+ if (referenceExpression == null) {
+ return;
+ }
+
+ FileObject file = ProjectUtils.getFileObjectForDocument(doc);
+ if (file == null) {
+ return;
+ }
+
+ Project project = getProjectForNavigation(file);
+ if (project == null) {
+ return;
+ }
+
+ navigationCache = OpenDeclarationKt.navigate(referenceExpression, project, file);
+ }
+
+ @Override
+ public Set<HyperlinkType> getSupportedHyperlinkTypes() {
+ return Sets.newHashSet(HyperlinkType.GO_TO_DECLARATION);
+ }
+
+ @Override
+ public String getTooltipText(Document doc, int offset, HyperlinkType type) {
+ return HoverUtilsKt.getToolTip(referenceExpression, doc, offset);
+ }
+
+ private Project getProjectForNavigation(FileObject fo) {
+ Project project = ProjectUtils.getKotlinProjectForFileObject(fo);
+ if (project != null) {
+ return project;
+ }
+ return ProjectUtils.getValidProject();
+ }
+
+ public Pair<Document, Integer> getNavigationCache() {
+ return navigationCache;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/fromJavaToKotlinNavigationUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/fromJavaToKotlinNavigationUtils.kt
new file mode 100644
index 0000000..0935dee
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/fromJavaToKotlinNavigationUtils.kt
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation.netbeans
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import java.io.IOException
+import javax.lang.model.element.ElementKind
+import javax.swing.text.Document
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
+import org.jetbrains.kotlin.filesystem.lightclasses.LightClassBuilderFactory
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.lang.java.ElementHandleFieldContainingClassSearcher
+import org.jetbrains.kotlin.resolve.lang.java.ElementHandleNameSearcher
+import org.jetbrains.kotlin.resolve.lang.java.ElementHandleSimpleNameSearcher
+import org.jetbrains.kotlin.resolve.lang.java.ElementSearcher
+import org.netbeans.api.java.source.JavaSource
+import org.netbeans.api.java.source.SourceUtils
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.project.Project
+import org.openide.util.Exceptions
+
+fun getElement(doc: Document?, offset: Int): ElementHandle<*>? {
+ val javaSource = JavaSource.forDocument(doc) ?: return null
+ val searcher = ElementSearcher(offset)
+ try {
+ javaSource.runUserActionTask(searcher, true)
+ } catch (ex: IOException) {
+ Exceptions.printStackTrace(ex)
+ }
+
+ return searcher.element
+}
+
+fun findKotlinFileToNavigate(element: ElementHandle<*>?, project: Project?, doc: Document): Pair<KtFile, Int>? {
+ if (element == null || project == null) return null
+
+ val ktFiles = ProjectUtils.getSourceFiles(project)
+
+ ktFiles.forEach {
+ if (element.kind == ElementKind.CLASS) {
+ val fqName = NoResolveFileClassesProvider.getFileClassInfo(it).fileClassFqName
+ if (fqName.asString() == element.qualifiedName) {
+ return Pair(it, 0)
+ }
+ }
+
+ val ktElement = findKotlinDeclaration(element, it, doc)
+ if (ktElement != null) {
+ val offset = ktElement.textOffset
+ return Pair(it, offset)
+ }
+ }
+
+ return null
+}
+
+private fun findKotlinDeclaration(element: ElementHandle<*>, ktFile: KtFile, doc: Document): KtElement? {
+ val result = arrayListOf<KtElement>()
+ val visitor = makeVisitor(element, result, doc)
+ if (visitor != null) {
+ ktFile.acceptChildren(visitor)
+ }
+
+ return result.firstOrNull()
+}
+
+private fun makeVisitor(element: ElementHandle<*>, result: MutableList<KtElement>, doc: Document): KtVisitorVoid? {
+ when (element.kind) {
+ ElementKind.CLASS,
+ ElementKind.INTERFACE,
+ ElementKind.ENUM -> return object : KtAllVisitor() {
+
+ override fun visitClassOrObject(ktClassOrObject: KtClassOrObject) {
+ if (ktClassOrObject.fqName?.asString() == element.qualifiedName) {
+ result.add(ktClassOrObject)
+ return
+ }
+ ktClassOrObject.acceptChildren(this)
+ }
+ }
+ ElementKind.FIELD -> return object : KtAllVisitor() {
+
+ override fun visitObjectDeclaration(declaration: KtObjectDeclaration) {
+ visitExplicitDeclaration(declaration)
+ declaration.acceptChildren(this)
+ }
+
+ override fun visitEnumEntry(enumEntry: KtEnumEntry) {
+ visitExplicitDeclaration(enumEntry)
+ }
+
+ override fun visitProperty(property: KtProperty) {
+ visitExplicitDeclaration(property)
+ }
+
+ private fun visitExplicitDeclaration(declaration: KtDeclaration?) {
+ declaration ?: return
+ val javaSource = JavaSource.forDocument(doc) ?: return
+ val searcher = ElementHandleNameSearcher(element)
+ try {
+ javaSource.runUserActionTask(searcher, true)
+ } catch (ex: IOException) {
+ Exceptions.printStackTrace(ex)
+ }
+ if (equalsNames(declaration, element, doc) && declaration.name == searcher.name.asString()) {
+ result.add(declaration)
+ }
+ }
+ }
+ ElementKind.METHOD,
+ ElementKind.CONSTRUCTOR -> return object : KtAllVisitor() {
+ override fun visitNamedFunction(function: KtNamedFunction) {
+ visitExplicitDeclaration(function)
+ }
+
+ override fun visitProperty(property: KtProperty) {
+ visitExplicitDeclaration(property)
+ property.acceptChildren(this)
+ }
+
+ override fun visitPropertyAccessor(accessor: KtPropertyAccessor) {
+ visitExplicitDeclaration(accessor)
+ }
+
+ override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {
+ visitExplicitDeclaration(constructor)
+ }
+
+ override fun visitPrimaryConstructor(constructor: KtPrimaryConstructor) {
+ visitExplicitDeclaration(constructor)
+
+ constructor.valueParameters.forEach {
+ if (it.valOrVarKeyword != null) {
+ visitExplicitDeclaration(it)
+ }
+ }
+ }
+
+ override fun visitClass(ktClass: KtClass) {
+ ktClass.acceptChildren(this)
+ }
+
+ private fun visitExplicitDeclaration(declaration: KtDeclaration?) {
+ if (declaration == null) return
+
+ if (equalsNames(declaration, element, doc) && equalsDeclaringTypes(declaration, element, doc)) {
+ result.add(declaration)
+ }
+ }
+ }
+ else -> return null
+ }
+}
+
+fun equalsNames(ktElement: KtElement?, element: ElementHandle<*>?, doc: Document): Boolean {
+ if (ktElement == null || element == null) return false
+ val first = ktElement.name ?: return false
+
+ val javaSource = JavaSource.forDocument(doc) ?: return false
+ val searcher = ElementHandleSimpleNameSearcher(element)
+ try {
+ javaSource.runUserActionTask(searcher, true)
+ } catch (ex: IOException) {
+ Exceptions.printStackTrace(ex)
+ }
+ val second = searcher.simpleName ?: return false
+
+ if (ktElement is KtValVarKeywordOwner && element.kind == ElementKind.METHOD) {
+ return equalsForProperty(ktElement, second)
+ }
+
+ if (first != second) return false
+
+ val ktSignatures: Set<Pair<String, String>> =
+ ktElement.getUserData(LightClassBuilderFactory.JVM_SIGNATURE) ?: return true
+ if (ktSignatures.isEmpty()) return true
+
+ val signatures = SourceUtils.getJVMSignature(element).toList()
+
+ ktSignatures.firstOrNull { signatures.contains(it.first) } ?: return false
+ return true
+}
+
+private fun equalsForProperty(ktProperty: KtValVarKeywordOwner, simpleName: String): Boolean {
+ val name = when (ktProperty) {
+ is KtProperty -> ktProperty.name
+ is KtParameter -> ktProperty.name
+ else -> null
+ } ?: return false
+
+ val propertyFromMethodName = simpleName.let {
+ if (simpleName.startsWith("is")) it else {
+ if (simpleName.length <= 3) return false
+ val withoutGetOrSet = it.substring(3)
+ withoutGetOrSet.replaceRange(0, 1, withoutGetOrSet.first().toLowerCase().toString())
+ }
+ }
+
+ return name == propertyFromMethodName
+}
+
+fun equalsDeclaringTypes(ktElement: KtElement?, element: ElementHandle<*>?, doc: Document): Boolean {
+ if (ktElement == null || element == null) return false
+
+ val typeNameInfo = getDeclaringTypeFqName(ktElement) ?: return false
+ val javaSource = JavaSource.forDocument(doc) ?: return false
+ val searcher = ElementHandleFieldContainingClassSearcher(element)
+ try {
+ javaSource.runUserActionTask(searcher, true)
+ } catch (ex: IOException) {
+ Exceptions.printStackTrace(ex)
+ }
+
+ val fqName = searcher.containingClass.qualifiedName ?: return false
+ return fqName == typeNameInfo.asString() || typeNameInfo.asString() == "${fqName}Kt"
+}
+
+private fun getDeclaringTypeFqName(ktElement: KtElement?): FqName? {
+ return PsiTreeUtil.getParentOfType(ktElement,
+ KtClassOrObject::class.java, KtFile::class.java)?.let { getTypeFqName(it) }
+}
+
+private fun getTypeFqName(element: PsiElement?) = when (element) {
+ is KtClassOrObject -> element.fqName
+ is KtFile -> NoResolveFileClassesProvider.getFileClassInfo(element).fileClassFqName
+ else -> null
+}
+
+private open class KtAllVisitor : KtVisitorVoid() {
+ override fun visitElement(element: PsiElement) {
+ element.acceptChildren(this)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/hoverUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/hoverUtils.kt
new file mode 100644
index 0000000..f6a77b3
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/hoverUtils.kt
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation.netbeans
+
+import javax.swing.text.Document
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.renderer.DescriptorRenderer
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.lang.java.getJavaDoc
+import org.jetbrains.kotlin.resolve.lang.java.resolver.NetBeansJavaSourceElement
+import org.jetbrains.kotlin.resolve.lang.java.structure.*
+import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
+import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
+import org.jetbrains.kotlin.utils.ProjectUtils
+
+fun getSmartCastHover(offset: Int): String? {
+ val ktFile = KotlinParser.file ?: return null
+ val analysisResult = KotlinParser.analysisResult ?: return null
+ val bindingContext = analysisResult.analysisResult.bindingContext
+
+ val element = ktFile.findElementAt(offset)
+ val expression = element?.getNonStrictParentOfType(KtSimpleNameExpression::class.java) ?: return null
+ val parentExpression = expression.parent
+
+ if (parentExpression is KtThisExpression || parentExpression is KtSuperExpression) return null
+
+ bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return null
+
+ val smartCast = bindingContext.get(BindingContext.SMARTCAST, expression)
+
+ return smartCast?.defaultType?.let { "Smart cast to ${DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it)}" }
+}
+
+fun getToolTip(referenceExpression: KtReferenceExpression?,
+ doc: Document, offset: Int): String {
+ val smartCast = getSmartCastHover(offset) ?: ""
+ referenceExpression ?: return smartCast
+
+ val file = ProjectUtils.getFileObjectForDocument(doc) ?: return smartCast
+ val project = ProjectUtils.getKotlinProjectForFileObject(file) ?: ProjectUtils.getValidProject() ?: return smartCast
+
+ val navigationData = getNavigationData(referenceExpression, project) ?: return smartCast
+ val sourceElement = navigationData.sourceElement
+
+ when (sourceElement) {
+ is KotlinSourceElement -> {
+ val descriptor = navigationData.descriptor
+ return "${descriptor.toString().substringBefore(" defined in")}${if (smartCast != "") "\n\n$smartCast" else ""}"
+ }
+ is NetBeansJavaSourceElement -> {
+ val handle = sourceElement.getElementBinding()
+ val javaDoc = handle.getJavaDoc(project)?.commentText()?.let { "\n\n$it" } ?: ""
+
+ val element = sourceElement.javaElement
+ when (element) {
+ is NetBeansJavaClass -> return "${element.presentation()}$javaDoc"
+ is NetBeansJavaMember<*> -> return "${element.presentation()}$javaDoc"
+ }
+
+ }
+ }
+
+ return ""
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/openDeclaration.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/openDeclaration.kt
new file mode 100644
index 0000000..d6d70f9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/netbeans/openDeclaration.kt
@@ -0,0 +1,223 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.navigation.netbeans
+
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.psi.KtReferenceExpression
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.resolver.NetBeansJavaSourceElement
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaElement
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaMember
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClass
+import org.jetbrains.kotlin.resolve.lang.java.findType
+import org.jetbrains.kotlin.resolve.lang.java.openInEditor
+import org.jetbrains.kotlin.resolve.lang.java.findMember
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.jetbrains.kotlin.navigation.references.createReferences
+import org.jetbrains.kotlin.psi.KtElement
+import org.openide.cookies.EditorCookie
+import org.openide.filesystems.FileObject
+import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
+import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
+import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement
+import javax.lang.model.element.ElementKind
+import com.intellij.psi.PsiElement
+import org.openide.filesystems.FileUtil
+import java.io.File
+import org.jetbrains.kotlin.navigation.*
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.utils.LineEndUtil
+import javax.swing.text.StyledDocument
+import org.netbeans.modules.editor.NbEditorUtilities
+import org.openide.loaders.DataObject
+import org.openide.text.NbDocument
+import org.openide.text.Line
+import javax.swing.text.Document
+import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
+import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
+import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
+import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.descriptors.MemberDescriptor
+import org.jetbrains.kotlin.resolve.NetBeansDescriptorUtils
+
+fun navigate(referenceExpression: KtReferenceExpression, project: Project, file: FileObject): Pair<Document, Int>? {
+ val data = getNavigationData(referenceExpression, project) ?: return null
+ return gotoElement(data.sourceElement, data.descriptor, referenceExpression, project, file)
+}
+
+private fun gotoElement(element: SourceElement, descriptor: DeclarationDescriptor,
+ fromElement: KtElement, project: Project, currentFile: FileObject): Pair<Document, Int>? {
+ when (element) {
+ is NetBeansJavaSourceElement -> {
+ var elementHandle = (element.javaElement as NetBeansJavaElement<*>).elementHandle.elementHandle ?: return null
+ if (elementHandle.kind == ElementKind.CONSTRUCTOR) {
+ val containingClass = (element.javaElement as NetBeansJavaMember<*>).containingClass
+ elementHandle = (containingClass as NetBeansJavaClass).elementHandle.elementHandle ?: return null
+ }
+
+ elementHandle.openInEditor(project)
+ }
+
+ is KotlinSourceElement -> return gotoKotlinDeclaration(element.psi, fromElement, currentFile)
+
+ is KotlinJvmBinarySourceElement -> gotoElementInBinaryClass(element.binaryClass, descriptor, project)
+
+ is KotlinJvmBinaryPackageSourceElement -> gotoClassByPackageSourceElement(element, descriptor, project)
+
+ else -> return null
+ }
+ return null
+}
+
+private fun gotoClassByPackageSourceElement(sourceElement: KotlinJvmBinaryPackageSourceElement,
+ descriptor: DeclarationDescriptor,
+ project: Project) {
+ if (descriptor !is DeserializedCallableMemberDescriptor) return
+
+ val binaryClass = sourceElement.getContainingBinaryClass(descriptor) ?: return
+ gotoElementInBinaryClass(binaryClass, descriptor, project)
+}
+
+private fun gotoElementInBinaryClass(binaryClass: KotlinJvmBinaryClass,
+ descriptor: DeclarationDescriptor,
+ project: Project) {
+ if (binaryClass !is VirtualFileKotlinClass) return
+
+ val className = if (KotlinClassHeader.Kind.MULTIFILE_CLASS == binaryClass.classHeader.kind) {
+ if (descriptor !is DeserializedCallableMemberDescriptor) return
+ getImplClassName(descriptor)?.asString() ?: return
+ } else binaryClass.classId.asSingleFqName().asString()
+
+ val elementHandle = project.findType(className)?.elementHandle ?: return
+ if (descriptor is MemberDescriptor) {
+ elementHandle.findMember(descriptor, project)?.openInEditor(project) ?: elementHandle.openInEditor(project)
+ } else elementHandle.openInEditor(project)
+}
+
+private fun getImplClassName(memberDescriptor: DeserializedCallableMemberDescriptor): Name? {
+ val nameIndex: Int
+
+ try
+ {
+ val getProtoMethod = DeserializedCallableMemberDescriptor::class.java.getMethod("getProto")
+ val proto = getProtoMethod!!.invoke(memberDescriptor)
+ val implClassNameField = Class.forName("org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf").getField("implClassName")
+ val implClassName = implClassNameField!!.get(null)
+ val protobufCallable = Class.forName("org.jetbrains.kotlin.serialization.ProtoBuf\$Callable")
+ val getExtensionMethod = protobufCallable!!.getMethod("getExtension", implClassName!!::class.java)
+ val indexObj = getExtensionMethod!!.invoke(proto, implClassName) as? Int ?: return null
+
+ nameIndex = indexObj
+ } catch (e: ReflectiveOperationException) {
+ KotlinLogger.INSTANCE.logException("", e)
+ return null
+ } catch (e: IllegalArgumentException) {
+ KotlinLogger.INSTANCE.logException("", e)
+ return null
+ } catch (e: SecurityException) {
+ KotlinLogger.INSTANCE.logException("", e)
+ return null
+ }
+
+ return memberDescriptor.nameResolver.getName(nameIndex)
+}
+
+private fun gotoKotlinDeclaration(psi: PsiElement, fromElement: KtElement,
+ currentFile: FileObject): Pair<Document, Int>? {
+ val declarationFile = findFileObjectForReferencedElement(psi, fromElement, currentFile) ?: return null
+ val document = ProjectUtils.getDocumentFromFileObject(declarationFile) ?: return null
+
+ val startOffset = LineEndUtil.convertCrToDocumentOffset(psi.containingFile.text, psi.textOffset)
+ openFileAtOffset(document, startOffset)
+ return Pair(document, startOffset)
+}
+
+private fun findFileObjectForReferencedElement(psi: PsiElement, fromElement: KtElement,
+ currentFile: FileObject): FileObject? {
+ if (fromElement.containingFile == psi.containingFile) return currentFile
+
+ val virtualFile = psi.containingFile.virtualFile ?: return null
+ var file = FileUtil.toFileObject(File(virtualFile.path))
+ if (file != null) return file
+
+ file = getFileObjectFromJar(virtualFile.path) ?: return null
+ return file
+}
+
+fun FileObject.openFileAtPosition(lineNumber: Int, columnNumber: Int) {
+ val dataObject = DataObject.find(this) ?: return
+ val editorCookie = dataObject.lookup.lookup(EditorCookie::class.java) ?: return
+
+ if (lineNumber == -1 || lineNumber == 0) editorCookie.open()
+
+ editorCookie.openDocument()
+ val line = editorCookie.lineSet.getOriginal(lineNumber - 1)
+ if (!line.isDeleted) {
+ line.show(Line.ShowOpenType.REUSE, Line.ShowVisibilityType.FOCUS, columnNumber)
+ }
+}
+
+fun openFileAtOffset(doc: StyledDocument, offset: Int) {
+ val line = NbEditorUtilities.getLine(doc, offset, false)
+ val colNumber = NbDocument.findLineColumn(doc, offset)
+ line.show(Line.ShowOpenType.OPEN, Line.ShowVisibilityType.FRONT, colNumber)
+}
+
+fun moveCaretToOffset(doc: StyledDocument, offset: Int) {
+ val line = NbEditorUtilities.getLine(doc, offset, false)
+ val colNumber = NbDocument.findLineColumn(doc, offset)
+ line.show(Line.ShowOpenType.NONE, Line.ShowVisibilityType.NONE, colNumber)
+}
+
+fun getElementWithSource(descriptor: DeclarationDescriptor, project: Project): SourceElement? {
+ val sourceElements = NetBeansDescriptorUtils.descriptorToDeclarations(descriptor, project)
+
+ return sourceElements.firstOrNull { it != SourceElement.NO_SOURCE }
+}
+
+fun getNavigationData(referenceExpression: KtReferenceExpression,
+ project: Project): NavigationData? {
+ val ktFile = referenceExpression.containingKtFile
+ val analysisResult = KotlinParser.getAnalysisResult(ktFile, project) ?: return null
+ val context = analysisResult.analysisResult.bindingContext
+
+ return createReferences(referenceExpression)
+ .asSequence()
+ .flatMap { it.getTargetDescriptors(context).asSequence() }
+ .mapNotNull {
+ val elementWithSource = getElementWithSource(it, project)
+ if (elementWithSource != null) NavigationData(elementWithSource, it) else null
+ }
+ .firstOrNull()
+}
+
+data class NavigationData(val sourceElement: SourceElement, val descriptor: DeclarationDescriptor)
+
+
+
+
+
+
+
+
+
+
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/references/KotlinReference.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/references/KotlinReference.kt
new file mode 100644
index 0000000..9ce860b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/references/KotlinReference.kt
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation.references
+
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.psi.KtReferenceExpression
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.psi.KtCallExpression
+import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
+import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
+import org.jetbrains.kotlin.psi.Call
+import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
+import org.jetbrains.kotlin.psi.KtNameReferenceExpression
+import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import com.intellij.util.SmartList
+import org.jetbrains.kotlin.utils.addIfNotNull
+import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
+
+interface KotlinReference {
+ val referenceExpression: KtReferenceExpression
+
+ fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
+}
+
+open class KotlinSimpleNameReference(override val referenceExpression: KtReferenceExpression) : KotlinReference {
+ override fun getTargetDescriptors(context: BindingContext) = referenceExpression.getReferenceTargets(context)
+}
+
+class KotlinInvokeFunctionReference(override val referenceExpression: KtCallExpression) : KotlinReference {
+ override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
+ val call = referenceExpression.getCall(context)
+ val resolvedCall = referenceExpression.getResolvedCall(context)
+
+ return when {
+ resolvedCall is VariableAsFunctionResolvedCall -> listOf(resolvedCall.functionCall.candidateDescriptor)
+ call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE -> listOf(resolvedCall.candidateDescriptor)
+ else -> emptyList()
+ }
+ }
+}
+
+sealed class KotlinSyntheticPropertyAccessorReference(override val referenceExpression: KtNameReferenceExpression, private val getter: Boolean)
+ : KotlinSimpleNameReference(referenceExpression) {
+ override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
+ val descriptors = super.getTargetDescriptors(context)
+ if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
+
+ val result = SmartList<FunctionDescriptor>()
+ descriptors
+ .filterIsInstance<SyntheticJavaPropertyDescriptor>()
+ .forEach {
+ if (getter) {
+ result.add(it.getMethod)
+ } else {
+ result.addIfNotNull(it.setMethod)
+ }
+ }
+ return result
+ }
+
+ class Getter(expression: KtNameReferenceExpression) : KotlinSyntheticPropertyAccessorReference(expression, true)
+ class Setter(expression: KtNameReferenceExpression) : KotlinSyntheticPropertyAccessorReference(expression, false)
+}
+
+class KotlinConstructorDelegationReference(override val referenceExpression: KtConstructorDelegationReferenceExpression) : KotlinReference {
+ override fun getTargetDescriptors(context: BindingContext) = referenceExpression.getReferenceTargets(context)
+}
+
+enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) {
+ READ(true, false), WRITE(false, true), READ_WRITE(true, true)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/references/referenceUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/references/referenceUtils.kt
new file mode 100644
index 0000000..4e95c22
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/navigation/references/referenceUtils.kt
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.navigation.references
+
+import java.util.ArrayList
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
+import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.utils.addToStdlib.constant
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.NetBeansDescriptorUtils
+import org.openide.filesystems.FileUtil
+import java.io.File
+import org.jetbrains.kotlin.utils.ProjectUtils
+
+inline private fun <reified T> ArrayList<KotlinReference>.register(e: KtElement, action: (T) -> KotlinReference) {
+ if (e is T) this.add(action(e))
+}
+
+inline private fun <reified T> ArrayList<KotlinReference>.registerMulti(e: KtElement, action: (T) -> List<KotlinReference>) {
+ if (e is T) this.addAll(action(e))
+}
+
+private fun KtExpression.readWriteAccess(): ReferenceAccess {
+ var expression = getQualifiedExpressionForSelectorOrThis()
+ loop@ while(true) {
+ val parent = expression.parent
+ when(parent) {
+ is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression
+ else -> break@loop
+ }
+ }
+
+ val assignment = expression.getAssignmentByLHS()
+ if (assignment != null) {
+ return when (assignment.operationToken) {
+ KtTokens.EQ -> ReferenceAccess.WRITE
+ else -> ReferenceAccess.READ_WRITE
+ }
+ }
+
+ return if ((expression.parent as? KtUnaryExpression)?.operationToken in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) })
+ ReferenceAccess.READ_WRITE
+ else
+ ReferenceAccess.READ
+}
+
+fun createReferences(element: KtReferenceExpression): List<KotlinReference> {
+ return arrayListOf<KotlinReference>().apply {
+ register<KtSimpleNameExpression>(element, ::KotlinSimpleNameReference)
+
+ register(element, ::KotlinInvokeFunctionReference)
+
+ register(element, ::KotlinConstructorDelegationReference)
+
+ registerMulti<KtNameReferenceExpression>(element) {
+ if (it.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMulti emptyList()
+
+ when (it.readWriteAccess()) {
+ ReferenceAccess.READ -> listOf(KotlinSyntheticPropertyAccessorReference.Getter(it))
+ ReferenceAccess.WRITE -> listOf(KotlinSyntheticPropertyAccessorReference.Setter(it))
+ ReferenceAccess.READ_WRITE -> listOf(
+ KotlinSyntheticPropertyAccessorReference.Getter(it),
+ KotlinSyntheticPropertyAccessorReference.Setter(it))
+ }
+ }
+ }
+}
+
+fun List<SourceElement>.getContainingClassOrObjectForConstructor()
+ = this.filterIsInstance(KotlinSourceElement::class.java)
+ .map { it.psi }
+ .filterIsInstance(KtConstructor::class.java)
+ .map { KotlinSourceElement(it.getContainingClassOrObject()) }
+
+fun KtReferenceExpression.getReferenceTargets(context: BindingContext): Collection<DeclarationDescriptor> {
+ val targetDescriptor = context[BindingContext.REFERENCE_TARGET, this]
+ return if (targetDescriptor != null) {
+ listOf(targetDescriptor)
+ } else {
+ context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this].orEmpty()
+ }
+}
+
+fun PsiElement.getReferenceExpression(): KtReferenceExpression? = PsiTreeUtil.getNonStrictParentOfType(this, KtReferenceExpression::class.java)
+
+fun KtElement.resolveToSourceDeclaration(): List<SourceElement> {
+ return when (this) {
+ is KtDeclaration -> listOf(KotlinSourceElement(this))
+
+ else -> {
+ val referenceExpression = getReferenceExpression() ?: return emptyList()
+
+ val reference = createReferences(referenceExpression)
+ reference.resolveToSourceElements()
+ }
+ }
+}
+
+fun List<KotlinReference>.resolveToSourceElements(): List<SourceElement> {
+ if (isEmpty()) return emptyList()
+
+ val ktFile = first().referenceExpression.containingKtFile
+ val path = ktFile.virtualFile.canonicalPath
+
+ val normalizedPath = FileUtil.normalizePath(path)
+
+ val file = FileUtil.toFileObject(File(normalizedPath)) ?: return emptyList()
+ val project = ProjectUtils.getKotlinProjectForFileObject(file) ?: return emptyList()
+
+ val analysisResult = KotlinParser.getAnalysisResult(ktFile, project) ?: return emptyList()
+
+ return this.resolveToSourceElements(
+ analysisResult.analysisResult.bindingContext, project)
+}
+
+fun List<KotlinReference>.resolveToSourceElements(context: BindingContext,
+ project: Project) = flatMap { it.getTargetDescriptors(context) }
+ .flatMap { NetBeansDescriptorUtils.descriptorToDeclarations(it, project) }
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/project/KotlinProjectConstants.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/project/KotlinProjectConstants.kt
new file mode 100644
index 0000000..480eabb
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/project/KotlinProjectConstants.kt
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.project
+
+enum class KotlinProjectConstants {
+ KOTLIN_SOURCE, JAVA_SOURCE, JAR
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/project/KotlinSources.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/project/KotlinSources.kt
new file mode 100644
index 0000000..d4a81e5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/project/KotlinSources.kt
@@ -0,0 +1,88 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.project
+
+import java.beans.PropertyChangeListener
+import javax.swing.ImageIcon
+import org.jetbrains.kotlin.builder.isKotlinFile
+import org.netbeans.api.project.Project
+import org.netbeans.api.project.SourceGroup
+import org.openide.filesystems.FileObject
+
+class KotlinSources(private val kotlinProject: Project) {
+
+ private fun findSrc(fo: FileObject,
+ files: MutableCollection<FileObject>,
+ type: KotlinProjectConstants?,
+ test: Boolean) {
+ if (fo.isFolder) {
+ if (!test && fo.name == "test" && fo.parent.name == "src") return
+ if (fo.name == "resources" &&
+ (fo.parent.name == "test" || fo.parent.name == "main")) return
+
+
+ fo.children.forEach { findSrc(it, files, type, test) }
+ } else when (type) {
+ KotlinProjectConstants.KOTLIN_SOURCE -> if (fo.isKotlinFile()) files.add(fo.parent)
+
+ KotlinProjectConstants.JAVA_SOURCE -> if (fo.hasExt("java")) files.add(fo.parent)
+
+ KotlinProjectConstants.JAR -> if (fo.hasExt("jar")) {
+ if (fo.parent.name != "build") files.add(fo.parent)
+ }
+ }
+ }
+
+ private fun getSrcDirectories(type: KotlinProjectConstants,
+ test: Boolean = true): List<FileObject> {
+ val orderedFiles = hashSetOf<FileObject>()
+ val srcDir = kotlinProject.projectDirectory.getFileObject("src") ?: return emptyList()
+
+ findSrc(srcDir, orderedFiles, type, test)
+ return orderedFiles.toList()
+ }
+
+ fun getAllKtFiles() = getSrcDirectories(KotlinProjectConstants.KOTLIN_SOURCE)
+ .flatMap { it.children.toList() }
+ .filter { it.hasExt("kt") }
+
+
+ fun getSourceGroups(type: KotlinProjectConstants,
+ test: Boolean = true) = getSrcDirectories(type, test)
+ .map { KotlinSourceGroup(it) }
+ .toTypedArray()
+
+}
+
+class KotlinSourceGroup(private val root: FileObject) : SourceGroup {
+
+ override fun getRootFolder() = root
+
+ override fun getName(): String = root.path
+
+ override fun getDisplayName(): String = rootFolder.name
+
+ override fun getIcon(bool: Boolean) = ImageIcon("org/jetbrains/kotlin.png")
+
+ override fun contains(fo: FileObject) = fo.toURI().toString().startsWith(rootFolder.toURI().toString())
+
+ override fun addPropertyChangeListener(pl: PropertyChangeListener?) {}
+
+ override fun removePropertyChangeListener(pl: PropertyChangeListener?) {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/ClassPathExtender.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/ClassPathExtender.kt
new file mode 100644
index 0000000..64ad252
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/ClassPathExtender.kt
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions
+
+import org.netbeans.api.java.classpath.ClassPath
+
+/*
+
+ @author baratynskiy
+ Created on Jan 11, 2017
+*/
+
+interface ClassPathExtender {
+ fun getProjectSourcesClassPath(type: String): ClassPath
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/KotlinPrivilegedTemplates.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/KotlinPrivilegedTemplates.kt
new file mode 100644
index 0000000..9573a06
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/KotlinPrivilegedTemplates.kt
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions
+
+import org.netbeans.spi.project.ui.PrivilegedTemplates
+
+/*
+
+ @author baratynskiy
+ Created on Jan 11, 2017
+*/
+
+class KotlinPrivilegedTemplates : PrivilegedTemplates {
+
+ override fun getPrivilegedTemplates() = arrayOf(
+ "Templates/Kotlin/class.kt",
+ "Templates/Kotlin/interface.kt",
+ "Templates/Kotlin/content.kt",
+ "Templates/Kotlin/enum.kt",
+ "Templates/Kotlin/object.kt",
+ "Templates/Classes/Class.java",
+ "Templates/Classes/Package",
+ "Templates/Classes/Interface.java",
+ "Templates/GUIForms/JPanel.java",
+ "Templates/GUIForms/JFrame.java"
+ )
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/KotlinProjectHelper.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/KotlinProjectHelper.kt
new file mode 100644
index 0000000..ac4339c
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/KotlinProjectHelper.kt
@@ -0,0 +1,137 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.projectsextensions
+
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.project.KotlinProjectConstants
+import org.jetbrains.kotlin.projectsextensions.gradle.classpath.GradleExtendedClassPath
+import org.jetbrains.kotlin.projectsextensions.j2se.classpath.J2SEExtendedClassPathProvider
+import org.jetbrains.kotlin.project.KotlinSources
+import org.jetbrains.kotlin.projectsextensions.maven.classpath.MavenExtendedClassPath
+import org.jetbrains.kotlin.resolve.lang.java.JavaEnvironment
+import org.netbeans.api.java.classpath.ClassPath
+import org.netbeans.api.project.Project
+import org.netbeans.spi.java.classpath.support.ClassPathSupport
+import org.openide.util.RequestProcessor
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+object KotlinProjectHelper {
+
+ private val kotlinSources = hashMapOf<Project, KotlinSources>()
+ private val extendedClassPaths = hashMapOf<Project, ClassPathExtender>()
+ private val fullClasspaths = hashMapOf<Project, ClassPath>()
+ private val environmentLoader = RequestProcessor("Kotlin Environment loader")
+ private val isScanning = hashMapOf<Project, Boolean>()
+ private val hasJavaFiles = hashMapOf<Project, Boolean>()
+
+ fun Project.isScanning() = isScanning[this] ?: false
+
+ fun postTask(run: Runnable): RequestProcessor.Task = environmentLoader.post(run)
+
+ fun hasJavaFiles(project: Project) = hasJavaFiles[project] ?: false
+
+ fun setHasJavaFiles(project: Project) = hasJavaFiles.put(project, true)
+
+ fun Project.doInitialScan() {
+ hasJavaFiles.put(this, getJavaFilesByProject(this).isNotEmpty())
+ JavaEnvironment.checkJavaSource(this)
+ }
+
+ fun Project.checkProject(): Boolean {
+ val className = this::class.java.name
+
+ return className == "org.netbeans.modules.java.j2seproject.J2SEProject"
+ || className == "org.netbeans.modules.maven.NbMavenProjectImpl"
+ || className == "org.netbeans.gradle.project.NbGradleProject"
+ }
+
+ fun Project.isMavenProject(): Boolean = this::class.java.name == "org.netbeans.modules.maven.NbMavenProjectImpl"
+
+ fun Project.removeProjectCache() {
+ kotlinSources.remove(this)
+ extendedClassPaths.remove(this)
+ fullClasspaths.remove(this)
+ }
+
+ fun Project.getKotlinSources(): KotlinSources? {
+ if (!checkProject()) return null
+
+ if (!kotlinSources.containsKey(this)) {
+ kotlinSources.put(this, KotlinSources(this))
+ }
+ return kotlinSources[this]
+ }
+
+ fun Project.getExtendedClassPath(): ClassPathExtender? {
+ if (!checkProject()) return null
+
+ if (!extendedClassPaths.containsKey(this)) {
+ when (this::class.java.name) {
+ "org.netbeans.modules.java.j2seproject.J2SEProject" -> extendedClassPaths.put(this, J2SEExtendedClassPathProvider(this))
+ "org.netbeans.modules.maven.NbMavenProjectImpl" -> extendedClassPaths.put(this, MavenExtendedClassPath(this))
+ "org.netbeans.gradle.project.NbGradleProject" -> extendedClassPaths.put(this, GradleExtendedClassPath(this))
+ }
+ }
+ return extendedClassPaths[this]
+ }
+
+ fun Project.getFullClassPath(): ClassPath? {
+ if (!fullClasspaths.containsKey(this)) {
+ val classpath = getExtendedClassPath() ?: return null
+
+ val boot = classpath.getProjectSourcesClassPath(ClassPath.BOOT)
+ val compile = classpath.getProjectSourcesClassPath(ClassPath.COMPILE)
+ val source = classpath.getProjectSourcesClassPath(ClassPath.SOURCE)
+ val proxy = ClassPathSupport.createProxyClassPath(boot, compile, source)
+
+ fullClasspaths.put(this, proxy)
+ }
+ return fullClasspaths[this]
+ }
+
+ private fun Project.updateFullClassPath() {
+ val classpath = getExtendedClassPath() ?: return
+
+ val boot = classpath.getProjectSourcesClassPath(ClassPath.BOOT)
+ val compile = classpath.getProjectSourcesClassPath(ClassPath.COMPILE)
+ val source = classpath.getProjectSourcesClassPath(ClassPath.SOURCE)
+ val proxy = ClassPathSupport.createProxyClassPath(boot, compile, source)
+ fullClasspaths.put(this, proxy)
+ }
+
+ fun Project.updateExtendedClassPath() {
+ when (this::class.java.name) {
+ "org.netbeans.modules.java.j2seproject.J2SEProject" -> extendedClassPaths.put(this, J2SEExtendedClassPathProvider(this))
+ "org.netbeans.modules.maven.NbMavenProjectImpl" -> extendedClassPaths.put(this, MavenExtendedClassPath(this))
+ "org.netbeans.gradle.project.NbGradleProject" -> extendedClassPaths.put(this, GradleExtendedClassPath(this))
+ }
+
+ updateFullClassPath()
+ JavaEnvironment.updateClasspathInfo(this)
+ KotlinEnvironment.updateKotlinEnvironment(this)
+ }
+
+ private fun getJavaFilesByProject(project: Project) = project.getKotlinSources()
+ ?.getSourceGroups(KotlinProjectConstants.JAVA_SOURCE)
+ ?.flatMap { it.rootFolder.children.toList() }
+ ?.filterTo(hashSetOf()) { it.ext == "java" }
+ ?.toSet() ?: emptySet()
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/GradleProjectOpenedHook.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/GradleProjectOpenedHook.kt
new file mode 100644
index 0000000..9181ab1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/GradleProjectOpenedHook.kt
@@ -0,0 +1,48 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.gradle
+
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.doInitialScan
+import org.netbeans.api.progress.ProgressHandleFactory
+import org.netbeans.api.project.Project
+import org.netbeans.spi.project.ui.ProjectOpenedHook
+import kotlin.concurrent.thread
+
+/**
+ *
+ * @author baratynskiy
+ */
+class GradleProjectOpenedHook(private val project: Project) : ProjectOpenedHook() {
+
+ override fun projectOpened() {
+ thread {
+ KotlinProjectHelper.postTask(Runnable {
+ val progressBar = ProgressHandleFactory.createHandle("Loading Kotlin environment")
+ progressBar.start()
+ KotlinEnvironment.getEnvironment(project)
+ progressBar.finish()
+ })
+
+ project.doInitialScan()
+ }
+ }
+
+ override fun projectClosed() {}
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/classpath/GradleExtendedClassPath.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/classpath/GradleExtendedClassPath.kt
new file mode 100644
index 0000000..5c5fa10
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/classpath/GradleExtendedClassPath.kt
@@ -0,0 +1,48 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.gradle.classpath
+
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.projectsextensions.ClassPathExtender
+import org.netbeans.api.java.classpath.ClassPath
+import org.netbeans.api.project.Project
+import org.netbeans.spi.java.classpath.ClassPathProvider
+
+/**
+ *
+ * @author baratynskiy
+ */
+class GradleExtendedClassPath(val project: Project) : ClassPathExtender {
+
+ private val classPathProvider: ClassPathProvider? = project.lookup.lookup(ClassPathProvider::class.java)
+
+ override fun getProjectSourcesClassPath(type: String): ClassPath =
+ if (classPathProvider == null) ClassPath.EMPTY else getClassPath(type)
+
+ private fun getClassPath(type: String): ClassPath {
+ try {
+ val method = classPathProvider?.javaClass?.getMethod("getClassPaths", String::class.java) ?: return ClassPath.EMPTY
+
+ return method.invoke(classPathProvider, type) as ClassPath
+ } catch (ex: ReflectiveOperationException) {
+ KotlinLogger.INSTANCE.logWarning(ex.message)
+
+ return ClassPath.EMPTY
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/lookup/GradleProjectLookupProviderExtension.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/lookup/GradleProjectLookupProviderExtension.java
new file mode 100644
index 0000000..0c2079a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/gradle/lookup/GradleProjectLookupProviderExtension.java
@@ -0,0 +1,40 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************** */
+package org.jetbrains.kotlin.projectsextensions.gradle.lookup;
+
+import org.jetbrains.kotlin.projectsextensions.KotlinPrivilegedTemplates;
+import org.jetbrains.kotlin.projectsextensions.gradle.GradleProjectOpenedHook;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.LookupProvider;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author baratynskiy
+ */
+public class GradleProjectLookupProviderExtension implements LookupProvider {
+
+ @Override
+ public Lookup createAdditionalLookup(Lookup lkp) {
+ Project project = lkp.lookup(Project.class);
+
+ return Lookups.fixed(new KotlinPrivilegedTemplates(),
+ new GradleProjectOpenedHook(project));
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/J2SEProjectOpenedHook.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/J2SEProjectOpenedHook.java
new file mode 100644
index 0000000..7857823
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/J2SEProjectOpenedHook.java
@@ -0,0 +1,75 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.projectsextensions.j2se;
+
+import org.jetbrains.kotlin.projectsextensions.j2se.buildextender.KotlinBuildExtender;
+import org.jetbrains.kotlin.model.KotlinEnvironment;
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.progress.ProgressHandleFactory;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.ui.ProjectOpenedHook;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class J2SEProjectOpenedHook extends ProjectOpenedHook {
+
+ private final Project project;
+
+ public J2SEProjectOpenedHook(Project project) {
+ this.project = project;
+ }
+
+ @Override
+ protected void projectOpened() {
+ Thread thread = new Thread() {
+ @Override
+ public void run() {
+ Runnable run = new Runnable() {
+ @Override
+ public void run() {
+ final ProgressHandle progressBar
+ = ProgressHandleFactory.createHandle("Loading Kotlin environment");
+ progressBar.start();
+ KotlinEnvironment.Companion.getEnvironment(project);
+ progressBar.finish();
+ }
+ };
+ KotlinProjectHelper.INSTANCE.postTask(run);
+ KotlinBuildExtender extender = new KotlinBuildExtender(project);
+ extender.addKotlinTasksToScript(project);
+
+ J2SEProjectPropertiesModifier propsModifier = new J2SEProjectPropertiesModifier(project);
+ propsModifier.turnOffCompileOnSave();
+ propsModifier.addKotlinRuntime();
+
+ KotlinProjectHelper.INSTANCE.doInitialScan(project);
+ }
+ };
+ thread.start();
+ }
+
+ @Override
+ protected void projectClosed() {
+ KotlinProjectHelper.INSTANCE.removeProjectCache(project);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/J2SEProjectPropertiesModifier.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/J2SEProjectPropertiesModifier.java
new file mode 100644
index 0000000..ef6534f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/J2SEProjectPropertiesModifier.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.j2se;
+
+
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+import org.jetbrains.kotlin.utils.KotlinClasspath;
+import org.codehaus.plexus.util.PropertyUtils;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.support.ant.EditableProperties;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class J2SEProjectPropertiesModifier {
+
+ private final Project project;
+
+ public J2SEProjectPropertiesModifier(Project project) {
+ this.project = project;
+ }
+
+ private String[] getModifiedClasspathProperty(EditableProperties editableProperties, String str) {
+ List<String> classpath = new ArrayList<>();
+ boolean hasKotlincClasspath = false;
+ for (String item : Arrays.asList(editableProperties.getProperty(str).split(":"))) {
+ classpath.add(item + ":");
+ if (item.equals("${kotlinc.classpath}")) {
+ hasKotlincClasspath = true;
+ }
+ }
+ if (!hasKotlincClasspath) {
+ classpath.add("${kotlinc.classpath}");
+ }
+
+ return classpath.toArray(new String[classpath.size()]);
+ }
+
+ public void addKotlinRuntime() {
+ FileObject root = project.getProjectDirectory();
+ FileObject nbproject = root.getFileObject("nbproject");
+ if (nbproject == null) {
+ return;
+ }
+
+ FileObject projectProps = nbproject.getFileObject("project.properties");
+ if (projectProps == null) {
+ return;
+ }
+
+ EditableProperties editableProperties = new EditableProperties(true);
+ try {
+ InputStream input = projectProps.getInputStream();
+ editableProperties.load(input);
+ editableProperties.setProperty("run.classpath", getModifiedClasspathProperty(editableProperties, "run.classpath"));
+ editableProperties.setProperty("javac.test.classpath", getModifiedClasspathProperty(editableProperties, "javac.test.classpath"));
+ editableProperties.setProperty("file.reference.kotlin-runtime.jar", KotlinClasspath.INSTANCE.getKotlinBootClasspath());
+ editableProperties.setProperty("kotlinc.classpath", "${file.reference.kotlin-runtime.jar}");
+ input.close();
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(projectProps.getPath()));
+ out.write("".getBytes());
+ out.flush();
+ editableProperties.store(out);
+ out.close();
+ } catch (FileNotFoundException ex) {
+ KotlinLogger.INSTANCE.logException("No project.properties file!", ex);
+ } catch (IOException ex) {
+ KotlinLogger.INSTANCE.logException("", ex);
+ }
+ }
+
+ public void turnOffCompileOnSave() {
+ FileObject root = project.getProjectDirectory();
+ FileObject nbproject = root.getFileObject("nbproject");
+ if (nbproject == null) {
+ return;
+ }
+
+ FileObject privateDir = nbproject.getFileObject("private");
+ if (privateDir == null) {
+ return;
+ }
+
+ FileObject privateProperties = privateDir.getFileObject("private.properties");
+ if (privateProperties == null) {
+ return;
+ }
+
+
+ try {
+ Properties props = PropertyUtils.loadProperties(privateProperties.toURL());
+ props.setProperty("compile.on.save", "false");
+ FileWriter writer = new FileWriter(privateProperties.getPath());
+ writer.write("");
+ writer.flush();
+ props.store(writer, "");
+ writer.close();
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/buildextender/KotlinBuildExtender.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/buildextender/KotlinBuildExtender.java
new file mode 100644
index 0000000..aaeed77
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/buildextender/KotlinBuildExtender.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.j2se.buildextender;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+import org.dom4j.tree.DefaultElement;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.netbeans.api.project.Project;
+import org.openide.filesystems.FileObject;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinBuildExtender {
+
+ private final Project project;
+
+ public KotlinBuildExtender(Project project) {
+ this.project = project;
+ }
+
+ public void addKotlinTasksToScript(Project project) {
+ FileObject buildImpl = getBuildImplXml(project);
+ if (buildImpl == null) {
+ return;
+ }
+ try {
+ addKotlinAnt(buildImpl);
+ addKotlinLibProperty(buildImpl);
+ insertWithKotlin(buildImpl);
+ } catch (DocumentException ex) {
+ KotlinLogger.INSTANCE.logException("No build-impl.xml!", ex);
+ } catch (IOException ex) {
+ KotlinLogger.INSTANCE.logException("", ex);
+ }
+ }
+
+ private FileObject getBuildImplXml(Project project) {
+ FileObject projDir=project.getProjectDirectory();
+ FileObject buildImpl = projDir.getFileObject("nbproject").getFileObject("build-impl.xml");
+
+ return buildImpl;
+ }
+
+ private void addKotlinLibProperty(FileObject buildImpl) throws DocumentException, UnsupportedEncodingException, IOException{
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(buildImpl.toURL());
+
+ List<Element> elements = document.getRootElement().elements("property");
+
+ for (Element el : elements) {
+ if (el.attribute("name").getValue().equals("kotlin.lib")) {
+ return;
+ }
+ }
+
+ DefaultElement prop = new DefaultElement("property");
+ prop.addAttribute("name", "kotlin.lib");
+ prop.addAttribute("value", ProjectUtils.KT_HOME + "lib");
+
+ List content = document.getRootElement().content();
+ if (content != null ) {
+ content.add(0, prop);
+ }
+
+ OutputFormat format = OutputFormat.createPrettyPrint();
+ FileWriter out = new FileWriter(buildImpl.getPath());
+ XMLWriter writer;
+ writer = new XMLWriter(out, format);
+ writer.write(document);
+ writer.close();
+ out.close();
+ }
+
+ private void addKotlinAnt(FileObject buildImpl) throws DocumentException, UnsupportedEncodingException, IOException {
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(buildImpl.toURL());
+
+ List<Element> elements = document.getRootElement().elements("typedef");
+ for (Element el : elements) {
+ if (el.attribute("classpath").getValue().equals("${kotlin.lib}/kotlin-ant.jar")) {
+ return;
+ }
+ }
+
+ DefaultElement typedef = new DefaultElement("typedef");
+ typedef.addAttribute("classpath", "${kotlin.lib}/kotlin-ant.jar");
+ typedef.addAttribute("resource", "org/jetbrains/kotlin/ant/antlib.xml");
+
+ List content = document.getRootElement().content();
+ if (content != null ) {
+ content.add(0, typedef);
+ }
+
+ OutputFormat format = OutputFormat.createPrettyPrint();
+ FileWriter out = new FileWriter(buildImpl.getPath());
+ XMLWriter writer;
+ writer = new XMLWriter(out, format);
+ writer.write(document);
+ writer.close();
+ out.close();
+ }
+
+ private void insertWithKotlin(FileObject buildImpl) throws DocumentException, IOException {
+ SAXReader reader = new SAXReader();
+ Document document = reader.read(buildImpl.toURL());
+ Element target = null;
+
+ List<Element> elements = document.getRootElement().elements("target");
+ for (Element el : elements) {
+ if (el.attribute("name").getValue().equals("-init-macrodef-javac-with-processors")) {
+ target = el;
+ }
+ }
+
+ if (target == null) {
+ return;
+ }
+
+ Element macrodef = target.element("macrodef");
+ if (macrodef == null) {
+ return;
+ }
+
+ Element sequential = macrodef.element("sequential");
+ if (sequential == null) {
+ return;
+ }
+
+ Element javac = sequential.element("javac");
+ if (javac == null) {
+ return;
+ }
+
+ if (javac.element("withKotlin") != null){
+ return;
+ }
+
+
+
+ DefaultElement withKotlin = new DefaultElement("withKotlin");
+
+ List content = javac.content();
+ if (content != null ) {
+ content.add(3, withKotlin);
+ }
+
+ OutputFormat format = OutputFormat.createPrettyPrint();
+ FileWriter out = new FileWriter(buildImpl.getPath());
+ XMLWriter writer;
+ writer = new XMLWriter(out, format);
+ writer.write(document);
+ writer.close();
+ out.close();
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/BootClassPathImplementation.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/BootClassPathImplementation.java
new file mode 100644
index 0000000..aa8a463
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/BootClassPathImplementation.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.j2se.classpath;
+
+import java.beans.PropertyChangeEvent;
+import org.netbeans.spi.java.classpath.ClassPathImplementation;
+import org.netbeans.spi.java.classpath.PathResourceImplementation;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.netbeans.api.java.classpath.ClassPath;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper;
+import org.jetbrains.kotlin.utils.KotlinClasspath;
+import org.netbeans.api.java.platform.JavaPlatform;
+import org.netbeans.api.java.platform.JavaPlatformManager;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.support.ant.PropertyEvaluator;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.WeakListeners;
+
+final class BootClassPathImplementation implements ClassPathImplementation, PropertyChangeListener {
+
+ private static final String PLATFORM_ACTIVE = "platform.active";
+ private static final String ANT_NAME = "java.platform.ant.name";
+ private static final String J2SE = "j2se";
+
+ private final PropertyEvaluator evaluator;
+ private JavaPlatformManager platformManager;
+ //name of project active platform
+ private String activePlatformName;
+ private List<PathResourceImplementation> resourcesCache;
+ private final PropertyChangeSupport support = new PropertyChangeSupport(this);
+ private long eventId;
+ private boolean isActivePlatformValid;
+ private final Project project;
+
+ public BootClassPathImplementation(Project project, PropertyEvaluator evaluator) {
+ assert evaluator != null;
+ this.evaluator = evaluator;
+ this.project = project;
+ evaluator.addPropertyChangeListener(WeakListeners.propertyChange(BootClassPathImplementation.this, evaluator));
+ }
+
+ @Override
+ public List<PathResourceImplementation> getResources() {
+ long currentId;
+ synchronized (this) {
+ if (this.resourcesCache != null) {
+ return this.resourcesCache;
+ }
+ currentId = eventId;
+ }
+
+ JavaPlatform jp = findActivePlatform ();
+ final List<PathResourceImplementation> result = new ArrayList<>();
+ if (jp != null) {
+ //TODO: May also listen on CP, but from Platform it should be fixed.
+ final ClassPath cp = jp.getBootstrapLibraries();
+ assert cp != null : jp;
+ for (ClassPath.Entry entry : cp.entries()) {
+ result.add(ClassPathSupport.createResource(entry.getURL()));
+ }
+ }
+
+
+ //Kotlin boot classpath
+ List<URL> kotlinBoot = getKotlinBootClassPath();
+ for (URL url : kotlinBoot){
+ result.add(ClassPathSupport.createResource(url));
+ }
+
+
+ synchronized (this) {
+ if (currentId == eventId) {
+ if (this.resourcesCache == null) {
+ this.resourcesCache = Collections.unmodifiableList(result);
+ }
+ return this.resourcesCache;
+ }
+ else {
+ return Collections.unmodifiableList (result);
+ }
+ }
+ }
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ this.support.addPropertyChangeListener (listener);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ this.support.removePropertyChangeListener (listener);
+ }
+
+ public List<URL> getKotlinBootClassPath(){
+ List<String> paths = new ArrayList<>();
+ List<URL> urls = new ArrayList<>();
+ paths.add(KotlinClasspath.INSTANCE.getKotlinBootClasspath());
+ for (String path : paths) {
+ File file = new File(path);
+ if (!file.canRead()) {
+ continue;
+ }
+
+ FileObject fileObject = FileUtil.toFileObject(file);
+ if (FileUtil.isArchiveFile(fileObject)) {
+ fileObject = FileUtil.getArchiveRoot(fileObject);
+ }
+ if (fileObject != null) {
+ urls.add(fileObject.toURL());
+ }
+ }
+ return urls;
+ }
+
+ protected JavaPlatform findActivePlatform () {
+ if (this.platformManager == null) {
+ this.platformManager = JavaPlatformManager.getDefault();
+ this.platformManager.addPropertyChangeListener(WeakListeners.propertyChange(this, this.platformManager));
+ }
+ this.activePlatformName = evaluator.getProperty(PLATFORM_ACTIVE);
+ final JavaPlatform activePlatform = platformManager.getDefaultPlatform();
+ this.isActivePlatformValid = activePlatform != null;
+ return activePlatform;
+ }
+
+// protected ScalaPlatform findActiveScalaPlatform () {
+// if (this.scalaPlatformManager == null) {
+// this.scalaPlatformManager = ScalaPlatformManager.getDefault();
+// this.scalaPlatformManager.addPropertyChangeListener(WeakListeners.propertyChange(this, this.platformManager));
+// }
+// this.activeScalaPlatformName = evaluator.getProperty(SCALA_PLATFORM_ACTIVE);
+//// final ScalaPlatform activePlatform = scalaPlatformManager.getDefaultPlatform();
+// final JavaPlatform activePlatform = J2SEProjectUtil.getActivePlatform (this.activePlatformName);
+//// this.isActiveScalaPlatformValid = activePlatform != null;
+// return activePlatform;
+// }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getSource() == this.evaluator && evt.getPropertyName().equals(PLATFORM_ACTIVE)) {
+ //Active platform was changed
+ resetCache ();
+ }
+ else if (evt.getSource() == this.platformManager && JavaPlatformManager.PROP_INSTALLED_PLATFORMS.equals(evt.getPropertyName()) && activePlatformName != null) {
+
+ }
+ }
+
+ /**
+ * Resets the cache and firesPropertyChange
+ */
+ private void resetCache () {
+ synchronized (this) {
+ resourcesCache = null;
+ eventId++;
+ }
+ support.firePropertyChange(PROP_RESOURCES, null, null);
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/J2SEExtendedClassPathProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/J2SEExtendedClassPathProvider.java
new file mode 100644
index 0000000..62126d5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/J2SEExtendedClassPathProvider.java
@@ -0,0 +1,474 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.j2se.classpath;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import org.jetbrains.kotlin.projectsextensions.ClassPathExtender;
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.modules.java.api.common.SourceRoots;
+import org.netbeans.spi.java.classpath.ClassPathFactory;
+import org.netbeans.spi.java.classpath.ClassPathProvider;
+import org.netbeans.spi.java.classpath.PathResourceImplementation;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.netbeans.spi.java.project.classpath.support.ProjectClassPathSupport;
+import org.netbeans.spi.project.support.ant.AntProjectHelper;
+import org.netbeans.spi.project.support.ant.PropertyEvaluator;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.Mutex;
+import org.openide.util.WeakListeners;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class J2SEExtendedClassPathProvider implements ClassPathProvider, PropertyChangeListener, ClassPathExtender {
+
+ private static final String BUILD_CLASSES_DIR = "build.classes.dir"; // NOI18N
+ private static final String DIST_JAR = "dist.jar"; // NOI18N
+ private static final String BUILD_TEST_CLASSES_DIR = "build.test.classes.dir"; // NOI18N
+ private static final String JAVAC_CLASSPATH = "javac.classpath"; //NOI18N
+ private static final String KOTLINC_CLASSPATH = "kotlinc.classpath";
+ private static final String JAVAC_TEST_CLASSPATH = "javac.test.classpath"; //NOI18N
+ private static final String RUN_CLASSPATH = "run.classpath"; //NOI18N
+ private static final String RUN_TEST_CLASSPATH = "run.test.classpath"; //NOI18N
+ private final AntProjectHelper helper;
+ private final File projectDirectory;
+ private final PropertyEvaluator evaluator;
+ private final SourceRoots sourceRoots;
+ private final SourceRoots testSourceRoots;
+ private final ClassPath[] cache = new ClassPath[8];
+ private final Map<String, FileObject> dirCache = new HashMap<>();
+ private final BootClassPathImplementation bootClassPathImpl;
+ private final Project project;
+
+ public J2SEExtendedClassPathProvider(Project project) {
+ Class projectClass = project.getClass();
+ this.project = project;
+ this.helper = getAntProjectHelper(projectClass, project);
+ this.projectDirectory = FileUtil.toFile(helper.getProjectDirectory());
+ assert this.projectDirectory != null;
+ this.evaluator = getEvaluator(projectClass, project);
+ this.sourceRoots = getSourceRoots(projectClass, project);
+ this.testSourceRoots = getTestSourceRoots(projectClass, project);
+ this.bootClassPathImpl = new BootClassPathImplementation(project, evaluator);
+ evaluator.addPropertyChangeListener(WeakListeners.propertyChange(J2SEExtendedClassPathProvider.this, evaluator));
+ }
+
+ private SourceRoots getTestSourceRoots(Class clazz, Project project) {
+ SourceRoots roots = null;
+
+ try {
+ Method ev = clazz.getMethod("getTestSourceRoots");
+ roots = (SourceRoots) ev.invoke(project);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return roots;
+ }
+
+ private SourceRoots getSourceRoots(Class clazz, Project project) {
+ SourceRoots roots = null;
+
+ try {
+ Method ev = clazz.getMethod("getSourceRoots");
+ roots = (SourceRoots) ev.invoke(project);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ assert roots != null : "SourceRoots NPE";
+
+ return roots;
+ }
+
+ private PropertyEvaluator getEvaluator(Class clazz, Project project) {
+ PropertyEvaluator eval = null;
+
+ try {
+ Method ev = clazz.getMethod("evaluator");
+ eval = (PropertyEvaluator) ev.invoke(project);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ assert eval != null : "PropertyEvaluator NPE";
+
+ return eval;
+ }
+
+ private AntProjectHelper getAntProjectHelper(Class clazz, Project project) {
+ AntProjectHelper helper = null;
+
+ try {
+ Method getAntProjectHelper = clazz.getMethod("getAntProjectHelper");
+ helper = (AntProjectHelper) getAntProjectHelper.invoke(project);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ assert helper != null : "AntProjectHelper NPE";
+
+ return helper;
+ }
+
+ private FileObject getDir(final String propname) {
+ return ProjectManager.mutex().readAccess(new Mutex.Action<FileObject>() {
+
+ @Override
+ public FileObject run() {
+ synchronized (J2SEExtendedClassPathProvider.this) {
+ FileObject fo = (FileObject) J2SEExtendedClassPathProvider.this.dirCache.get(propname);
+ if (fo == null || !fo.isValid()) {
+ String prop = evaluator.getProperty(propname);
+ if (prop != null) {
+ fo = helper.resolveFileObject(prop);
+ J2SEExtendedClassPathProvider.this.dirCache.put(propname, fo);
+ }
+ }
+ return fo;
+ }
+ }
+ });
+ }
+
+ private FileObject[] getPrimarySrcPath() {
+ return this.sourceRoots.getRoots();
+ }
+
+ private FileObject[] getTestSrcDir() {
+ return this.testSourceRoots.getRoots();
+ }
+
+ private FileObject getBuildClassesDir() {
+ return getDir(BUILD_CLASSES_DIR);
+ }
+
+ private FileObject getDistJar() {
+ return getDir(DIST_JAR);
+ }
+
+ private FileObject getBuildTestClassesDir() {
+ return getDir(BUILD_TEST_CLASSES_DIR);
+ }
+
+ /**
+ * Find what a given file represents.
+ * @param file a file in the project
+ * @return one of: <dl>
+ * <dt>0</dt> <dd>normal source</dd>
+ * <dt>1</dt> <dd>test source</dd>
+ * <dt>2</dt> <dd>built class (unpacked)</dd>
+ * <dt>3</dt> <dd>built test class</dd>
+ * <dt>4</dt> <dd>built class (in dist JAR)</dd>
+ * <dt>-1</dt> <dd>something else</dd>
+ * </dl>
+ */
+ public int getType(FileObject file) {
+ FileObject[] srcPath = getPrimarySrcPath();
+ for (FileObject root : srcPath) {
+ if (root.equals(file) || FileUtil.isParentOf(root, file)) {
+ return 0;
+ }
+ }
+ srcPath = getTestSrcDir();
+ for (FileObject root : srcPath) {
+ if (root.equals(file) || FileUtil.isParentOf(root, file)) {
+ return 1;
+ }
+ }
+ FileObject dir = getBuildClassesDir();
+ if (dir != null && (dir.equals(file) || FileUtil.isParentOf(dir, file))) {
+ return 2;
+ }
+ dir = getDistJar(); // not really a dir at all, of course
+ if (dir != null && dir.equals(FileUtil.getArchiveFile(file))) {
+ // XXX check whether this is really the root
+ return 4;
+ }
+ dir = getBuildTestClassesDir();
+ if (dir != null && (dir.equals(file) || FileUtil.isParentOf(dir, file))) {
+ return 3;
+ }
+ return -1;
+ }
+
+ private ClassPath getCompileTimeClasspath(FileObject file) {
+ int type = getType(file);
+ return this.getCompileTimeClasspath(type);
+ }
+
+ private synchronized ClassPath getCompileTimeClasspath(int type) {
+ if (type < 0 || type > 1) {
+ // Not a source file.
+ return null;
+ }
+
+ ClassPath cp = cache[2 + type];
+ if (cp == null) {
+ List<PathResourceImplementation> resources = new ArrayList<>();
+
+
+ List<URL> kotlinBoot = bootClassPathImpl.getKotlinBootClassPath();
+ for (URL url : kotlinBoot){
+ resources.add(ClassPathSupport.createResource(url));
+ }
+
+ if (type == 0) {
+ cp = ClassPathFactory.createClassPath(
+ ProjectClassPathSupport.createPropertyBasedClassPathImplementation(
+ projectDirectory, evaluator, new String[]{JAVAC_CLASSPATH, KOTLINC_CLASSPATH})); // NOI18N
+ } else {
+ cp = ClassPathFactory.createClassPath(
+ ProjectClassPathSupport.createPropertyBasedClassPathImplementation(
+ projectDirectory, evaluator, new String[]{JAVAC_TEST_CLASSPATH, KOTLINC_CLASSPATH})); // NOI18N
+ }
+
+ for (ClassPath.Entry entry : cp.entries()) {
+ resources.add(ClassPathSupport.createResource(entry.getURL()));
+ }
+ cp = ClassPathSupport.createClassPath(resources);
+
+ cache[2 + type] = cp;
+ }
+ return cp;
+ }
+
+ private ClassPath getRunTimeClasspath(FileObject file) {
+ int type = getType(file);
+ if (type < 0 || type > 4) {
+ // Unregistered file, or in a JAR.
+ // For jar:file:$projdir/dist/*.jar!/**/*.class, it is misleading to use
+ // run.classpath since that does not actually contain the file!
+ // (It contains file:$projdir/build/classes/ instead.)
+ return null;
+ } else if (type > 1) {
+ type -= 2; //Compiled source transform into source
+ }
+ return getRunTimeClasspath(type);
+ }
+
+ private synchronized ClassPath getRunTimeClasspath(final int type) {
+ ClassPath cp = cache[4 + type];
+ if (cp == null) {
+ List<PathResourceImplementation> resources = new ArrayList<>();
+
+ List<URL> kotlinBoot = bootClassPathImpl.getKotlinBootClassPath();
+ for (URL url : kotlinBoot){
+ resources.add(ClassPathSupport.createResource(url));
+ }
+
+ switch (type) {
+ case 0:
+ cp = ClassPathFactory.createClassPath(
+ ProjectClassPathSupport.createPropertyBasedClassPathImplementation(
+ projectDirectory, evaluator, new String[]{RUN_CLASSPATH, KOTLINC_CLASSPATH})); // NOI18N
+ break;
+ case 1:
+ cp = ClassPathFactory.createClassPath(
+ ProjectClassPathSupport.createPropertyBasedClassPathImplementation(
+ projectDirectory, evaluator, new String[]{RUN_TEST_CLASSPATH, KOTLINC_CLASSPATH}));
+
+ break;
+ case 2:
+ cp = ClassPathFactory.createClassPath(
+ ProjectClassPathSupport.createPropertyBasedClassPathImplementation(
+ projectDirectory, evaluator, new String[]{DIST_JAR, KOTLINC_CLASSPATH})); // NOI18N
+ break;
+ default:
+ break;
+ }
+
+ for (ClassPath.Entry entry : cp.entries()) {
+ resources.add(ClassPathSupport.createResource(entry.getURL()));
+ }
+ cp = ClassPathSupport.createClassPath(resources);
+
+ cache[4 + type] = cp;
+ }
+ return cp;
+ }
+
+ private ClassPath getSourcepath(FileObject file) {
+ int type = getType(file);
+ return this.getSourcepath(type);
+ }
+
+ private synchronized ClassPath getSourcepath(int type) {
+ if (type < 0 || type > 1) {
+ return null;
+ }
+ ClassPath cp = cache[type];
+ if (cp == null) {
+ switch (type) {
+ case 0:
+ cp = ClassPathFactory.createClassPath(new SourcePathImplementation(this.sourceRoots, helper, evaluator));
+ break;
+ case 1:
+ cp = ClassPathFactory.createClassPath(new SourcePathImplementation(this.testSourceRoots, helper, evaluator));
+ break;
+ }
+ }
+ cache[type] = cp;
+ return cp;
+ }
+
+ private synchronized ClassPath getBootClassPath() {
+ ClassPath cp = cache[7];
+ if (cp == null) {
+ cp = ClassPathFactory.createClassPath(new BootClassPathImplementation(project, evaluator));
+ cache[7] = cp;
+ }
+ return cp;
+ }
+
+ @Override
+ public ClassPath findClassPath(FileObject file, String type) {
+ if (type.equals(ClassPath.COMPILE)) {
+ return getCompileTimeClasspath(file);
+ } else if (type.equals(ClassPath.EXECUTE)) {
+ return getRunTimeClasspath(file);
+ } else if (type.equals(ClassPath.SOURCE)) {
+ return getSourcepath(file);
+ } else if (type.equals(ClassPath.BOOT)) {
+ return getBootClassPath();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns array of all classpaths of the given type in the project.
+ * The result is used for example for GlobalPathRegistry registrations.
+ */
+ public ClassPath[] getProjectClassPaths(final String type) {
+ return ProjectManager.mutex().readAccess(new Mutex.Action<ClassPath[]>() {
+
+ @Override
+ public ClassPath[] run() {
+ if (ClassPath.BOOT.equals(type)) {
+ return new ClassPath[]{getBootClassPath()};
+ }
+ if (ClassPath.COMPILE.equals(type)) {
+ ClassPath[] l = new ClassPath[2];
+ l[0] = getCompileTimeClasspath(0);
+ l[1] = getCompileTimeClasspath(1);
+ return l;
+ }
+ if (ClassPath.SOURCE.equals(type)) {
+ ClassPath[] l = new ClassPath[2];
+ l[0] = getSourcepath(0);
+ l[1] = getSourcepath(1);
+ return l;
+ }
+ assert false;
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Returns the given type of the classpath for the project sources
+ * (i.e., excluding tests roots).
+ */
+ @Override
+ public ClassPath getProjectSourcesClassPath(String type) {
+ if (ClassPath.BOOT.equals(type)) {
+ return getBootClassPath();
+ }
+ if (ClassPath.COMPILE.equals(type)) {
+ return getCompileTimeClasspath(0);
+ }
+ if (ClassPath.SOURCE.equals(type)) {
+ return getSourcepath(0);
+ }
+ if (ClassPath.EXECUTE.equals(type)) {
+ return getRunTimeClasspath(0);
+ }
+ assert false;
+ return null;
+ }
+
+ @Override
+ public synchronized void propertyChange(PropertyChangeEvent evt) {
+ dirCache.remove(evt.getPropertyName());
+ KotlinProjectHelper.INSTANCE.updateExtendedClassPath(project);
+ }
+
+ public String[] getPropertyName(final SourceRoots roots, final String type) {
+ if (roots.isTest()) {
+ if (ClassPath.COMPILE.equals(type)) {
+ return new String[] {JAVAC_TEST_CLASSPATH};
+ } else if (ClassPath.EXECUTE.equals(type)) {
+ return new String[]{RUN_TEST_CLASSPATH};
+ } else {
+ return null;
+ }
+ } else {
+ if (ClassPath.COMPILE.equals(type)) {
+ return new String[] {JAVAC_CLASSPATH};
+ } else if (ClassPath.EXECUTE.equals(type)) {
+ return new String[]{RUN_CLASSPATH};
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public String[] getPropertyName(SourceGroup sg, String type) {
+ FileObject root = sg.getRootFolder();
+ FileObject[] path = getPrimarySrcPath();
+ for (FileObject path1 : path) {
+ if (root.equals(path1)) {
+ if (ClassPath.COMPILE.equals(type)) {
+ return new String[]{JAVAC_CLASSPATH};
+ } else if (ClassPath.EXECUTE.equals(type)) {
+ return new String[]{RUN_CLASSPATH};
+ } else {
+ return null;
+ }
+ }
+ }
+ path = getTestSrcDir();
+ for (FileObject path1 : path) {
+ if (root.equals(path1)) {
+ if (ClassPath.COMPILE.equals(type)) {
+ return new String[]{JAVAC_TEST_CLASSPATH};
+ } else if (ClassPath.EXECUTE.equals(type)) {
+ return new String[]{RUN_TEST_CLASSPATH};
+ } else {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/SourcePathImplementation.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/SourcePathImplementation.java
new file mode 100644
index 0000000..fda8064
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/classpath/SourcePathImplementation.java
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.j2se.classpath;
+
+import java.beans.PropertyChangeEvent;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.net.URI;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import org.netbeans.modules.java.api.common.SourceRoots;
+import org.netbeans.modules.java.api.common.project.ProjectProperties;
+import org.netbeans.spi.java.classpath.ClassPathImplementation;
+import org.netbeans.spi.java.classpath.PathResourceImplementation;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.netbeans.spi.java.classpath.FilteringPathResourceImplementation;
+import org.netbeans.spi.project.support.ant.AntProjectHelper;
+import org.netbeans.spi.project.support.ant.PathMatcher;
+import org.netbeans.spi.project.support.ant.PropertyEvaluator;
+import org.openide.filesystems.FileChangeAdapter;
+import org.openide.filesystems.FileChangeListener;
+import org.openide.filesystems.FileEvent;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+import org.openide.util.WeakListeners;
+
+/**
+ * Implementation of a single classpath that is derived from one Ant property.
+ */
+final class SourcePathImplementation implements ClassPathImplementation, PropertyChangeListener {
+
+ private static final String PROP_BUILD_DIR = "build.dir"; //NOI18N
+ private static final String DIR_GEN_BINDINGS = "generated/addons"; // NOI18N
+ private static RequestProcessor REQ_PROCESSOR = new RequestProcessor(); // No I18N
+ private final PropertyChangeSupport support = new PropertyChangeSupport(this);
+ private List<PathResourceImplementation> resources;
+ private final SourceRoots sourceRoots;
+ private final AntProjectHelper projectHelper;
+ private final PropertyEvaluator evaluator;
+ private FileChangeListener fcl = null;
+
+ /**
+ * Construct the implementation.
+ * @param sourceRoots used to get the roots information and events
+ * @param projectHelper used to obtain the project root
+ */
+ public SourcePathImplementation(SourceRoots sourceRoots, AntProjectHelper projectHelper, PropertyEvaluator evaluator) {
+ assert sourceRoots != null && projectHelper != null && evaluator != null;
+ this.sourceRoots = sourceRoots;
+ sourceRoots.addPropertyChangeListener(this);
+ this.projectHelper = projectHelper;
+ this.evaluator = evaluator;
+ evaluator.addPropertyChangeListener(this);
+ }
+
+ private synchronized void createListener(String buildDir, String[] paths) {
+ if (this.fcl == null) {
+ // Need to keep reference to fcl.
+ // See JavaDoc for org.openide.util.WeakListeners
+ FileObject prjFo = this.projectHelper.getProjectDirectory();
+ this.fcl = new AddOnGeneratedSourceRootListner(prjFo, buildDir,
+ paths);
+ ((AddOnGeneratedSourceRootListner) this.fcl).listenToProjRoot();
+ }
+ }
+
+ private List<PathResourceImplementation> getGeneratedSrcRoots(String buildDir, String[] paths) {
+ List<PathResourceImplementation> ret =
+ new ArrayList<PathResourceImplementation>();
+
+ File buidDirFile = projectHelper.resolveFile(buildDir);
+ for (String path : paths) {
+ File genAddOns = new File(buidDirFile, path);
+ if (genAddOns.exists() && genAddOns.isDirectory()) {
+ File[] subDirs = genAddOns.listFiles();
+ for (File subDir : subDirs) {
+ try {
+ URL url = subDir.toURI().toURL();
+ if (!subDir.exists()) {
+ assert !url.toExternalForm().endsWith("/"); //NOI18N
+ url = new URL(url.toExternalForm() + '/'); //NOI18N
+ }
+ ret.add(ClassPathSupport.createResource(url));
+ } catch (MalformedURLException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+ private void invalidate() {
+ synchronized (this) {
+ this.resources = null;
+ }
+ this.support.firePropertyChange(PROP_RESOURCES, null, null);
+ }
+
+ public List<PathResourceImplementation> getResources() {
+ synchronized (this) {
+ if (this.resources != null) {
+ return this.resources;
+ }
+ }
+ URL[] roots = sourceRoots.getRootURLs();
+ synchronized (this) {
+ if (this.resources == null) {
+ List<PathResourceImplementation> result = new ArrayList<PathResourceImplementation>(roots.length);
+ for (final URL root : roots) {
+ class PRI implements FilteringPathResourceImplementation, PropertyChangeListener {
+
+ PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+ PathMatcher matcher;
+
+ PRI() {
+ evaluator.addPropertyChangeListener(WeakListeners.propertyChange(this, evaluator));
+ }
+
+ public URL[] getRoots() {
+ return new URL[]{root};
+ }
+
+ public boolean includes(URL root, String resource) {
+ if (matcher == null) {
+ matcher = new PathMatcher(
+ evaluator.getProperty(ProjectProperties.INCLUDES),
+ evaluator.getProperty(ProjectProperties.EXCLUDES),
+ new File(URI.create(root.toExternalForm())));
+ }
+ return matcher.matches(resource, true);
+ }
+
+ public ClassPathImplementation getContent() {
+ return null;
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ pcs.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ pcs.removePropertyChangeListener(listener);
+ }
+
+ public void propertyChange(PropertyChangeEvent ev) {
+ String prop = ev.getPropertyName();
+ if (prop == null || prop.equals(ProjectProperties.INCLUDES) || prop.equals(ProjectProperties.EXCLUDES)) {
+ matcher = null;
+ PropertyChangeEvent ev2 = new PropertyChangeEvent(this, FilteringPathResourceImplementation.PROP_INCLUDES, null, null);
+ ev2.setPropagationId(ev);
+ pcs.firePropertyChange(ev2);
+ }
+ }
+ }
+ result.add(new PRI());
+ }
+ // adds java artifacts generated by wscompile and wsimport to resources to be available for code completion
+ try {
+ String buildDir = this.evaluator.getProperty(PROP_BUILD_DIR);
+ if (buildDir != null) {
+ // generated/wsclient
+ File f = new File(this.projectHelper.resolveFile(buildDir), "generated/wsclient"); //NOI18N
+ URL url = f.toURI().toURL();
+ if (!f.exists()) { //NOI18N
+ assert !url.toExternalForm().endsWith("/"); //NOI18N
+ url = new URL(url.toExternalForm() + '/'); //NOI18N
+ }
+ result.add(ClassPathSupport.createResource(url));
+
+ // generated/wsimport/client
+ f = new File(this.projectHelper.resolveFile(buildDir), "generated/wsimport/client"); //NOI18N
+ url = f.toURI().toURL();
+ if (!f.exists()) { //NOI18N
+ assert !url.toExternalForm().endsWith("/"); //NOI18N
+ url = new URL(url.toExternalForm() + '/'); //NOI18N
+ }
+ result.add(ClassPathSupport.createResource(url));
+
+ // generated/addons/<subDirs>
+ result.addAll(getGeneratedSrcRoots(buildDir,
+ new String[]{DIR_GEN_BINDINGS}));
+ // Listen for any new Source root creation.
+ createListener(buildDir,
+ new String[]{DIR_GEN_BINDINGS});
+ }
+ } catch (MalformedURLException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ this.resources = Collections.unmodifiableList(result);
+ }
+ return this.resources;
+ }
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ support.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ support.removePropertyChangeListener(listener);
+ }
+
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (SourceRoots.PROP_ROOTS.equals(evt.getPropertyName())) {
+ invalidate();
+ } else if (this.evaluator != null && evt.getSource() == this.evaluator &&
+ (evt.getPropertyName() == null || PROP_BUILD_DIR.equals(evt.getPropertyName()))) {
+ invalidate();
+ }
+ }
+
+ /**
+ * Thread to get newly created source root for each File/Folder create event.
+ **/
+ private static class SourceRootScannerTask implements Runnable {
+
+ SourcePathImplementation spi = null;
+ FileChangeListener fcl = null;
+ List<List<String>> paths = null;
+ FileObject parent = null;
+ FileObject child = null;
+ List<String> listnerAddedDirs = new ArrayList<String>();
+
+ public SourceRootScannerTask(SourcePathImplementation s,
+ FileChangeListener origFcl, List<List<String>> pths,
+ FileObject parent, FileObject child) {
+ this.spi = s;
+ this.fcl = origFcl;
+ this.paths = pths;
+ this.parent = parent;
+ this.child = child;
+ }
+
+ private void firePropertyChange() {
+ this.spi.invalidate();
+ }
+
+ private void addListners(List<String> path, int cIndx) {
+ int size = path.size();
+ FileObject currParent = this.parent;
+ FileObject curr = this.child;
+ String relDir = null;
+ FileChangeListener weakFcl = null;
+ for (int i = cIndx; i < size; i++) {
+ curr = currParent.getFileObject(path.get(i));
+ if ((curr != null) && (curr.isFolder())) {
+ relDir = FileUtil.getRelativePath(this.parent, curr);
+ if (!this.listnerAddedDirs.contains(relDir)) {
+ this.listnerAddedDirs.add(relDir);
+ weakFcl = FileUtil.weakFileChangeListener(this.fcl,
+ curr);
+ curr.addFileChangeListener(weakFcl);
+ }
+
+ if (i == (size - 1)) {
+ if (curr.getChildren().length > 0) {
+ firePropertyChange();
+ }
+ break;
+ }
+
+ currParent = curr;
+ } else {
+ break;
+ }
+ }
+ }
+
+ public void run() {
+ Iterator<List<String>> itr = paths.iterator();
+ List<String> path = null;
+ int cIndx = -1;
+ int pIndx = -1;
+ boolean lastElem = false;
+
+ while (itr.hasNext()) {
+ path = itr.next();
+ cIndx = path.indexOf(child.getName());
+ pIndx = path.indexOf(parent.getName());
+
+ lastElem = ((pIndx + 1) == path.size()) ? true : false;
+
+ if (lastElem) {
+ if (cIndx == -1) {
+ firePropertyChange();
+ }
+ } else {
+ if ((cIndx != -1) && (pIndx == (cIndx - 1))) {
+ // Add listner and fire change event if leaf directory
+ // is created.
+ addListners(path, cIndx);
+ }
+ }
+ }
+ }
+ }
+
+ private class AddOnGeneratedSourceRootListner extends FileChangeAdapter {
+ // Path is relative to project root starting with project specific
+ // build directory.
+ private List<List<String>> paths = Collections.synchronizedList(
+ new ArrayList<List<String>>());
+ private FileObject projRoot;
+
+ AddOnGeneratedSourceRootListner(FileObject pr, String bd, String[] addOnPaths) {
+ this.projRoot = pr;
+ StringTokenizer stk = null;
+ List<String> pathElems = null;
+ for (String path : addOnPaths) {
+ stk = new StringTokenizer(path, "/"); // No I18N
+ pathElems = new ArrayList<String>();
+ pathElems.add(bd);
+ while (stk.hasMoreTokens()) {
+ pathElems.add(stk.nextToken());
+ }
+ this.paths.add(pathElems);
+ }
+ }
+
+ /**
+ * Listen to all the folders from ProjectRoot, build upto any existing
+ * addons dirs.
+ **/
+ public synchronized void listenToProjRoot() {
+ List<String> dirsAdded = new ArrayList<String>();
+ String relativePath = null;
+ FileObject fo = this.projRoot;
+ FileChangeListener weakFcl = FileUtil.weakFileChangeListener(this,
+ fo);
+ fo.addFileChangeListener(weakFcl);
+ FileObject parent = null;
+ FileObject child = null;
+ for (List<String> path : paths) {
+ parent = fo;
+ for (String pathElem : path) {
+ child = parent.getFileObject(pathElem);
+ if (child != null) {
+ relativePath = FileUtil.getRelativePath(fo, child);
+ if (!dirsAdded.contains(relativePath)) {
+ dirsAdded.add(relativePath);
+ weakFcl = FileUtil.weakFileChangeListener(this,
+ child);
+ child.addFileChangeListener(weakFcl);
+ parent = child;
+ }
+ } else {
+ // No need to check further down.
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void fileFolderCreated(FileEvent fe) {
+ synchronized (this) {
+ SourceRootScannerTask task = new SourceRootScannerTask(
+ SourcePathImplementation.this,
+ this,
+ this.paths,
+ (FileObject) fe.getSource(),
+ fe.getFile());
+ SourcePathImplementation.REQ_PROCESSOR.post(task);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/lookup/J2SEProjectLookupProviderExtension.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/lookup/J2SEProjectLookupProviderExtension.java
new file mode 100644
index 0000000..6e7e8f0
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/j2se/lookup/J2SEProjectLookupProviderExtension.java
@@ -0,0 +1,46 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.projectsextensions.j2se.lookup;
+
+import org.jetbrains.kotlin.projectsextensions.KotlinPrivilegedTemplates;
+import org.jetbrains.kotlin.projectsextensions.j2se.J2SEProjectOpenedHook;
+import org.jetbrains.kotlin.projectsextensions.j2se.classpath.J2SEExtendedClassPathProvider;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.LookupProvider;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class J2SEProjectLookupProviderExtension implements LookupProvider {
+
+ @Override
+ public Lookup createAdditionalLookup(Lookup lkp) {
+ final Project j2seProject = lkp.lookup(Project.class);
+
+ return Lookups.fixed(
+ new KotlinPrivilegedTemplates(),
+ new J2SEExtendedClassPathProvider(j2seProject),
+ new J2SEProjectOpenedHook(j2seProject)
+ );
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/MavenHelper.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/MavenHelper.java
new file mode 100644
index 0000000..355d0fd
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/MavenHelper.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.swing.ImageIcon;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.project.MavenProject;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.jetbrains.kotlin.projectsextensions.maven.buildextender.PomXmlModifier;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.netbeans.modules.maven.api.NbMavenProject;
+import org.openide.awt.NotificationDisplayer;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class MavenHelper {
+
+ private static final Map<Project, List<? extends Project>> depProjects = new HashMap<>();
+
+ private static final List<Project> askedToConfigure = new ArrayList<>();
+
+ public static void configure(Project project) {
+ if (askedToConfigure.contains(project)) {
+ return;
+ }
+
+ MavenProject mavenProject = getOriginalMavenProject(project);
+ if (mavenProject == null) return;
+ if (!kotlinPluginConfigured(mavenProject)) {
+ final PomXmlModifier pomModifier = new PomXmlModifier(project);
+ ActionListener listener = new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ pomModifier.checkPom();
+ }
+ };
+ NotificationDisplayer.getDefault().notify("Kotlin is not configured",
+ new ImageIcon(ImageUtilities.loadImage("org/jetbrains/kotlin/kotlin.png")),
+ "Configure Kotlin", listener);
+ }
+
+ askedToConfigure.add(project);
+ }
+
+ private static boolean kotlinPluginConfigured(MavenProject mavenProject) {
+ Set<Artifact> pluginArtifacts = mavenProject.getPluginArtifacts();
+ if (pluginArtifacts == null) return false;
+
+ for (Artifact plugin : pluginArtifacts) {
+ String groupId = plugin.getGroupId();
+ String artifactId = plugin.getArtifactId();
+
+ if (groupId.equals("org.jetbrains.kotlin")
+ && artifactId.equals("kotlin-maven-plugin")) return true;
+ }
+
+ return false;
+ }
+
+ public static boolean hasParent(Project project) {
+ return getParentProjectDirectory(project.getProjectDirectory()) != null;
+ }
+
+ public static MavenProject getOriginalMavenProject(Project proj) {
+ Class clazz = proj.getClass();
+ try {
+ Method getOriginalProject = clazz.getMethod("getOriginalMavenProject");
+ return (MavenProject) getOriginalProject.invoke(proj);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return null;
+ }
+
+ public static NbMavenProject getProjectWatcher(Project proj) {
+ Class clazz = proj.getClass();
+ try {
+ Method getProjectWatcher = clazz.getMethod("getProjectWatcher");
+ return (NbMavenProject) getProjectWatcher.invoke(proj);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return null;
+ }
+
+ @Nullable
+ public static Project getMavenProject(FileObject dir) throws IOException {
+ if (dir == null) {
+ return null;
+ }
+
+ if (ProjectManager.getDefault().isProject(dir)){
+ return ProjectManager.getDefault().findProject(dir);
+ }
+
+ return null;
+ }
+
+ public static boolean isModuled(Project project) {
+ MavenProject originalProject = getOriginalMavenProject(project);
+ if (originalProject == null) {
+ return false;
+ }
+ return !originalProject.getModules().isEmpty();
+ }
+
+ public static boolean isMavenMainModuledProject(Project project) {
+ if (isModuled(project)) {
+ try {
+ if (getMavenProject(project.getProjectDirectory().getParent()) == null) {
+ return true;
+ }
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ return false;
+ }
+
+ private static FileObject getParentProjectDirectory(FileObject proj) {
+ if (ProjectManager.getDefault().isProject(proj.getParent())) {
+ FileObject parent = getParentProjectDirectory(proj.getParent());
+
+ if (parent != null) {
+ return parent;
+ }
+ return proj.getParent();
+ }
+
+ return null;
+ }
+
+ private static FileObject getMainParentFolder(Project proj) {
+ FileObject projDir = proj.getProjectDirectory();
+ FileObject parent = projDir;
+ while (projDir != null) {
+ projDir = getParentProjectDirectory(projDir);
+ if (projDir != null) {
+ parent = projDir;
+ }
+ }
+
+ return parent;
+ }
+
+ public static Project getMainParent(Project proj) throws IOException {
+ Project parent = getMavenProject(getParentProjectDirectory(proj.getProjectDirectory()));
+ return parent != null ? parent : proj;
+ }
+
+ private static Set<FileObject> allModules(FileObject parent) {
+ Set<FileObject> modules = Sets.newHashSet();
+ modules.add(parent);
+
+ for (FileObject fo : parent.getChildren()) {
+ if (fo.isFolder() && fo.getFileObject("pom.xml") != null) {
+ modules.addAll(allModules(fo));
+ }
+ }
+
+ return modules;
+ }
+
+ public static List<? extends Project> getDependencyProjects(Project project){
+ if (depProjects.get(project) == null) {
+ depProjects.put(project, findDependencyProjects(project));
+ }
+
+ return depProjects.get(project);
+ }
+
+ private static List<? extends Project> findDependencyProjects(Project project){
+ List<Project> dependencyProjects = new ArrayList<>();
+ MavenProject originalProject = getOriginalMavenProject(project);
+ if (originalProject == null) {
+ return dependencyProjects;
+ }
+ List compileDependencies = originalProject.getCompileDependencies();
+ List<String> dependencies = Lists.newArrayList();
+
+ for (Object dependency : compileDependencies) {
+ dependencies.add(((Dependency) dependency).getArtifactId());
+ }
+
+ FileObject mainParentFolder = getMainParentFolder(project);
+ Set<FileObject> allModules = allModules(mainParentFolder);
+ Set<FileObject> moduleDependencies = Sets.newHashSet();
+
+ for (FileObject module : allModules) {
+ if (dependencies.contains(module.getName())) {
+ moduleDependencies.add(module);
+ }
+ }
+
+ for (FileObject module : moduleDependencies) {
+ try {
+ Project dep = getMavenProject(module);
+ if (dep != null) {
+ dependencyProjects.add(dep);
+ }
+ } catch (IOException ex) {
+ KotlinLogger.INSTANCE.logException("Can't find module " + module.getName(), ex);
+ }
+ }
+
+ return dependencyProjects;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/MavenProjectOpenedHook.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/MavenProjectOpenedHook.java
new file mode 100644
index 0000000..1efd8db
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/MavenProjectOpenedHook.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.reflect.Method;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.jetbrains.kotlin.model.KotlinEnvironment;
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.progress.ProgressHandleFactory;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.maven.api.NbMavenProject;
+import org.netbeans.spi.project.ui.ProjectOpenedHook;
+import org.openide.filesystems.FileAttributeEvent;
+import org.openide.filesystems.FileChangeListener;
+import org.openide.filesystems.FileEvent;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileRenameEvent;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class MavenProjectOpenedHook extends ProjectOpenedHook{
+
+ private static volatile boolean progressHandleRun = false;
+ private final Project project;
+
+ public MavenProjectOpenedHook(Project project) {
+ this.project = project;
+ }
+
+ @Override
+ protected void projectOpened() {
+ Thread thread = new Thread(){
+ @Override
+ public void run(){
+ Runnable run = new Runnable(){
+ @Override
+ public void run(){
+ progressHandleRun = true;
+ final ProgressHandle progressBar =
+ ProgressHandleFactory.createHandle("Loading Kotlin environment");
+ progressBar.start();
+ KotlinEnvironment.Companion.getEnvironment(project);
+ progressBar.finish();
+ progressHandleRun = false;
+ }
+ };
+ if (!progressHandleRun) {
+ KotlinProjectHelper.INSTANCE.postTask(run);
+ }
+
+ PomXmlChangeListener pomListener = new PomXmlChangeListener(project);
+ final FileObject pomXml = project.getProjectDirectory().getFileObject("pom.xml");
+
+ if (pomXml != null) {
+ pomXml.addFileChangeListener(pomListener);
+ getProjectWatcher().addPropertyChangeListener(pomListener);
+ }
+
+ KotlinProjectHelper.INSTANCE.doInitialScan(project);
+ }
+ };
+ thread.start();
+ }
+ private NbMavenProject getProjectWatcher() {
+ Class clazz = project.getClass();
+ try {
+ Method getProjectWatcher = clazz.getMethod("getProjectWatcher");
+ return (NbMavenProject) getProjectWatcher.invoke(project);
+ } catch (ReflectiveOperationException ex) {}
+
+ return null;
+ }
+ @Override
+ protected void projectClosed() {
+ KotlinProjectHelper.INSTANCE.removeProjectCache(project);
+ }
+
+ private static class PomXmlChangeListener implements PropertyChangeListener, FileChangeListener {
+
+ private final Project project;
+ private boolean changed = false;
+
+ public PomXmlChangeListener(Project project) {
+ this.project = project;
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (changed) {
+ KotlinLogger.INSTANCE.logInfo("CHANGED");
+ KotlinProjectHelper.INSTANCE.updateExtendedClassPath(project);
+ changed = false;
+ }
+ }
+
+ @Override
+ public void fileFolderCreated(FileEvent fe) {}
+
+ @Override
+ public void fileDataCreated(FileEvent fe) {}
+
+ @Override
+ public void fileChanged(FileEvent fe) {
+ changed = true;
+ }
+
+ @Override
+ public void fileDeleted(FileEvent fe) {}
+
+ @Override
+ public void fileRenamed(FileRenameEvent fre) {}
+
+ @Override
+ public void fileAttributeChanged(FileAttributeEvent fae) {}
+
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/buildextender/PomXmlModifier.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/buildextender/PomXmlModifier.java
new file mode 100644
index 0000000..59dc876
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/buildextender/PomXmlModifier.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven.buildextender;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.QName;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+import org.dom4j.tree.DefaultElement;
+import org.jetbrains.kotlin.bundledcompiler.BundledCompiler;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.netbeans.api.project.Project;
+import org.openide.util.Exceptions;
+
+public class PomXmlModifier {
+
+ private final Project project;
+ private final String groupIdName = "org.jetbrains.kotlin";
+
+ public PomXmlModifier(Project project) {
+ this.project = project;
+ }
+
+ public void checkPom() {
+ try {
+ checkKotlinStdLibDependency();
+ checkKotlinPlugin();
+ } catch (DocumentException | IOException ex) {
+ KotlinLogger.INSTANCE.logException("Cannot find pom.xml", ex);
+ }
+ }
+
+ private Element createDependenciesElement(Element root) {
+ QName qname = new QName("dependencies", root.getQName().getNamespace());
+ DefaultElement dependenciesElement = new DefaultElement(qname);
+
+ root.content().add(dependenciesElement);
+
+ return root.element("dependencies");
+ }
+
+ private Element createBuildElement(Element root) {
+ QName qname = new QName("build", root.getQName().getNamespace());
+ DefaultElement buildElement = new DefaultElement(qname);
+
+ root.content().add(buildElement);
+
+ return root.element("build");
+ }
+
+ private Element createPluginsElement(Element root) {
+ QName qname = new QName("plugins", root.getQName().getNamespace());
+ DefaultElement pluginsElement = new DefaultElement(qname);
+
+ root.content().add(pluginsElement);
+
+ return root.element("plugins");
+ }
+
+ private void createStdlibDependency(Element dependencies) {
+ QName dependencyQname = new QName("dependency", dependencies.getQName().getNamespace());
+ DefaultElement dependency = new DefaultElement(dependencyQname);
+
+ QName groupIdQname = new QName("groupId", dependencies.getQName().getNamespace());
+ DefaultElement groupId = new DefaultElement(groupIdQname);
+ groupId.addText(groupIdName);
+
+ QName artifactIdQname = new QName("artifactId", dependencies.getQName().getNamespace());
+ DefaultElement artifactId = new DefaultElement(artifactIdQname);
+ artifactId.addText("kotlin-stdlib");
+
+ QName versionQname = new QName("version", dependencies.getQName().getNamespace());
+ DefaultElement version = new DefaultElement(versionQname);
+ version.addText(BundledCompiler.KOTLIN_VERSION);
+
+ dependency.add(groupId);
+ dependency.add(artifactId);
+ dependency.add(version);
+
+ dependencies.content().add(dependency);
+ }
+
+ private void addExecution(Element executions, String id, String phase, String goal) {
+ QName executionQname1 = new QName("execution", executions.getQName().getNamespace());
+ DefaultElement execution = new DefaultElement(executionQname1);
+
+ QName idQname1 = new QName("id", executions.getQName().getNamespace());
+ DefaultElement id1 = new DefaultElement(idQname1);
+ id1.addText(id);
+ QName phaseQname1 = new QName("phase", executions.getQName().getNamespace());
+ DefaultElement phase1 = new DefaultElement(phaseQname1);
+ phase1.addText(phase);
+ QName goalsQname1 = new QName("goals", executions.getQName().getNamespace());
+ DefaultElement goals1 = new DefaultElement(goalsQname1);
+ QName goalQname1 = new QName("goal", executions.getQName().getNamespace());
+ DefaultElement goal1 = new DefaultElement(goalQname1);
+ goal1.addText(goal);
+
+ goals1.add(goal1);
+
+ execution.add(id1);
+ execution.add(phase1);
+ execution.add(goals1);
+
+ executions.add(execution);
+ }
+
+ private void addExecutions(Element plugin) {
+ QName executionsQname = new QName("executions", plugin.getQName().getNamespace());
+ DefaultElement executions = new DefaultElement(executionsQname);
+
+ addExecution(executions, "compile", "process-sources", "compile");
+ addExecution(executions, "test-compile", "process-test-sources", "test-compile");
+
+ plugin.add(executions);
+ }
+
+ private void createPluginElement(Element plugins) {
+ QName pluginQname = new QName("plugin", plugins.getQName().getNamespace());
+ DefaultElement plugin = new DefaultElement(pluginQname);
+
+ QName groupIdQname = new QName("groupId", plugins.getQName().getNamespace());
+ DefaultElement groupId = new DefaultElement(groupIdQname);
+ groupId.addText(groupIdName);
+
+ QName artifactIdQname = new QName("artifactId", plugins.getQName().getNamespace());
+ DefaultElement artifactId = new DefaultElement(artifactIdQname);
+ artifactId.addText("kotlin-maven-plugin");
+
+ QName versionQname = new QName("version", plugins.getQName().getNamespace());
+ DefaultElement version = new DefaultElement(versionQname);
+ version.addText(BundledCompiler.KOTLIN_VERSION);
+
+ plugin.add(groupId);
+ plugin.add(artifactId);
+ plugin.add(version);
+
+ addExecutions(plugin);
+
+ plugins.add(plugin);
+ }
+
+ private File getPOMFile(Project proj) {
+ Class clazz = proj.getClass();
+ try {
+ Method method = clazz.getMethod("getPOMFile");
+ return (File) method.invoke(proj);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return null;
+ }
+
+ private void checkKotlinStdLibDependency() throws DocumentException, IOException {
+ File pom = getPOMFile(project);
+ if (pom == null) {
+ return;
+ }
+ SAXReader reader = new SAXReader();
+ Document pomDocument = reader.read(pom);
+
+ Element root = pomDocument.getRootElement();
+ Element dependencies = root.element("dependencies");
+ if (dependencies == null) {
+ dependencies = createDependenciesElement(root);
+ }
+
+ Element stdlibDependency = null;
+ for (Object el : dependencies.elements("dependency")) {
+ Element dep = (Element) el;
+ Element groupId = dep.element("groupId");
+ Element artifactId = dep.element("artifactId");
+ if (groupId == null || artifactId == null) {
+ continue;
+ }
+ if (groupId.getText().equals(groupIdName) &&
+ artifactId.getText().equals("kotlin-stdlib")) {
+ stdlibDependency = dep;
+ break;
+ }
+ }
+
+ if (stdlibDependency == null) {
+ createStdlibDependency(dependencies);
+ }
+
+ OutputFormat format = OutputFormat.createPrettyPrint();
+ FileWriter out = new FileWriter(pom);
+ XMLWriter writer;
+ writer = new XMLWriter(out, format);
+ writer.write(pomDocument);
+ out.close();
+ }
+
+ public boolean hasKotlinPluginInPom() throws DocumentException {
+ File pom = getPOMFile(project);
+ if (pom == null) {
+ return false;
+ }
+ SAXReader reader = new SAXReader();
+ Document pomDocument = reader.read(pom);
+
+ Element root = pomDocument.getRootElement();
+ Element build = root.element("build");
+ if (build == null) {
+ return false;
+ }
+
+ Element plugins = build.element("plugins");
+ if (plugins == null) {
+ return false;
+ }
+
+ Element plugin = null;
+ for (Object el : plugins.elements("plugin")) {
+ Element plug = (Element) el;
+ Element groupId = plug.element("groupId");
+ Element artifactId = plug.element("artifactId");
+ if (groupId == null || artifactId == null) {
+ continue;
+ }
+ if (groupId.getText().equals(groupIdName) &&
+ artifactId.getText().equals("kotlin-maven-plugin")) {
+ plugin = plug;
+ break;
+ }
+ }
+
+ return plugin != null;
+ }
+
+ private void checkKotlinPlugin() throws DocumentException, IOException {
+ File pom = getPOMFile(project);
+ if (pom == null) {
+ return;
+ }
+ SAXReader reader = new SAXReader();
+ Document pomDocument = reader.read(pom);
+
+ Element root = pomDocument.getRootElement();
+ Element build = root.element("build");
+ if (build == null) {
+ build = createBuildElement(root);
+ }
+
+ Element plugins = build.element("plugins");
+ if (plugins == null) {
+ plugins = createPluginsElement(build);
+ }
+
+ Element plugin = null;
+ for (Object el : plugins.elements("plugin")) {
+ Element plug = (Element) el;
+ Element groupId = plug.element("groupId");
+ Element artifactId = plug.element("artifactId");
+ if (groupId == null || artifactId == null) {
+ continue;
+ }
+ if (groupId.getText().equals(groupIdName) &&
+ artifactId.getText().equals("kotlin-maven-plugin")) {
+ plugin = plug;
+ break;
+ }
+ }
+
+ if (plugin != null) {
+ return;
+ }
+
+ createPluginElement(plugins);
+
+ OutputFormat format = OutputFormat.createPrettyPrint();
+ FileWriter out = new FileWriter(pom);
+ XMLWriter writer;
+ writer = new XMLWriter(out, format);
+ writer.write(pomDocument);
+ out.close();
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/classpath/MavenExtendedClassPath.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/classpath/MavenExtendedClassPath.java
new file mode 100644
index 0000000..e799e1d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/classpath/MavenExtendedClassPath.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven.classpath;
+
+import com.google.common.collect.Lists;
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.project.MavenProject;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.jetbrains.kotlin.projectsextensions.ClassPathExtender;
+import org.jetbrains.kotlin.projectsextensions.maven.MavenHelper;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.platform.JavaPlatform;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.java.classpath.ClassPathProvider;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class MavenExtendedClassPath implements ClassPathExtender {
+
+ private final Project project;
+ private ClassPath boot = null;
+ private ClassPath compile = null;
+ private ClassPath execute = null;
+ private ClassPath source = null;
+
+ public MavenExtendedClassPath(Project project) {
+ this.project = project;
+ createClasspath();
+ }
+
+ private ClassPath getClasspath(List<String> paths) throws DependencyResolutionRequiredException, MalformedURLException {
+ Set<URL> classpaths = new HashSet<>();
+ if (paths == null) {
+ return ClassPath.EMPTY;
+ }
+ Set<String> classpath = new HashSet<>();
+ classpath.addAll(paths);
+
+ for (String path : classpath) {
+ if (path == null) continue;
+
+ File file = new File(path);
+ if (!file.exists() || !file.canRead()) {
+ continue;
+ }
+
+ FileObject fileObject = FileUtil.toFileObject(file);
+ if (FileUtil.isArchiveFile(fileObject)) {
+ fileObject = FileUtil.getArchiveRoot(fileObject);
+ }
+ if (fileObject != null) {
+ classpaths.add(fileObject.toURL());
+ }
+ }
+
+ return ClassPathSupport.createClassPath(classpaths.toArray(new URL[classpaths.size()]));
+ }
+
+ private List<String> getCompileClasspathElements(Project proj) throws DependencyResolutionRequiredException {
+ MavenProject mavenProj = MavenHelper.getOriginalMavenProject(proj);
+ if (mavenProj == null) {
+ return Collections.emptyList();
+ }
+
+ List<String> compileClasspath = Lists.newArrayList();
+ List<String> dependencyProjectsNames = Lists.newArrayList();
+ for (Project depProj : MavenHelper.getDependencyProjects(proj)) {
+ dependencyProjectsNames.add(depProj.getProjectDirectory().getName());
+ }
+
+ Set<Artifact> artifacts = mavenProj.getArtifacts();
+ for (Artifact artifact : artifacts) {
+ if (dependencyProjectsNames.contains(artifact.getArtifactId())) continue;
+
+ File artifactFile = artifact.getFile();
+ if (artifactFile == null) continue;
+
+ compileClasspath.add(artifactFile.getAbsolutePath());
+ }
+
+ return compileClasspath;
+ }
+
+ private List<String> getRuntimeClasspathElements(Project proj) throws DependencyResolutionRequiredException {
+ MavenProject mavenProj = MavenHelper.getOriginalMavenProject(proj);
+ if (mavenProj == null) {
+ return Collections.emptyList();
+ }
+ List<String> runtimeClasspath = mavenProj.getRuntimeClasspathElements();
+ if (runtimeClasspath == null || runtimeClasspath.isEmpty()) {
+ KotlinLogger.INSTANCE.logInfo(proj.getProjectDirectory().getPath() +
+ " runtime classpath is empty");
+ }
+
+ return runtimeClasspath;
+ }
+
+ private List<String> getCompileSourceRoots(Project proj) throws DependencyResolutionRequiredException {
+ MavenProject mavenProj = MavenHelper.getOriginalMavenProject(proj);
+ if (mavenProj == null) {
+ return Collections.emptyList();
+ }
+ List<String> compileClasspath = mavenProj.getCompileSourceRoots();
+ if (compileClasspath == null || compileClasspath.isEmpty()) {
+ KotlinLogger.INSTANCE.logInfo(proj.getProjectDirectory().getPath() +
+ " compile source roots are empty");
+ }
+
+ return compileClasspath;
+ }
+
+ private List<String> getSystemClasspathElements(Project proj) throws DependencyResolutionRequiredException {
+ MavenProject mavenProj = MavenHelper.getOriginalMavenProject(proj);
+ if (mavenProj == null) {
+ return Collections.emptyList();
+ }
+ List<String> systemClasspath = mavenProj.getSystemClasspathElements();
+ if (systemClasspath == null || systemClasspath.isEmpty()) {
+ KotlinLogger.INSTANCE.logInfo(proj.getProjectDirectory().getPath() +
+ " system classpath is empty");
+ }
+
+ return systemClasspath;
+ }
+
+ private JavaPlatform getJavaPlatform(Project project) {
+ ClassPathProvider provider = project.getLookup().lookup(ClassPathProvider.class);
+ if (provider == null) return null;
+
+ try {
+ Method method = provider.getClass().getMethod("getJavaPlatform");
+ return (JavaPlatform) method.invoke(provider);
+ } catch (ReflectiveOperationException ex) {
+ Exceptions.printStackTrace(ex);
+ return null;
+ }
+ }
+
+ private List<String> getTestClasspathElements(Project proj) throws DependencyResolutionRequiredException {
+ MavenProject mavenProj = MavenHelper.getOriginalMavenProject(proj);
+ if (mavenProj == null) {
+ return Collections.emptyList();
+ }
+ List<String> testClasspath = mavenProj.getTestClasspathElements();
+ if (testClasspath == null || testClasspath.isEmpty()) {
+ KotlinLogger.INSTANCE.logInfo(proj.getProjectDirectory().getPath() +
+ " test classpath is empty");
+ }
+
+ return testClasspath;
+ }
+
+ private void createClasspath() {
+ try {
+ compile = getClasspath(getCompileClasspathElements(project));
+ execute = getClasspath(getRuntimeClasspathElements(project));
+ source = getClasspath(getCompileSourceRoots(project));
+
+ JavaPlatform javaPlatform = getJavaPlatform(project);
+ if (javaPlatform != null) {
+ boot = javaPlatform.getBootstrapLibraries();
+ } else {
+ boot = ClassPath.EMPTY;
+ }
+
+ List<String> javaClasspathElements = new ArrayList<>();
+ javaClasspathElements.addAll(getTestClasspathElements(project));
+ compile = ClassPathSupport.createProxyClassPath(compile,
+ getClasspath(javaClasspathElements));
+
+ } catch (DependencyResolutionRequiredException | MalformedURLException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ @Override
+ public ClassPath getProjectSourcesClassPath(String type) {
+ switch (type) {
+ case ClassPath.COMPILE:
+ return compile;
+ case ClassPath.EXECUTE:
+ return execute;
+ case ClassPath.SOURCE:
+ return source;
+ case ClassPath.BOOT:
+ return boot;
+ default:
+ return ClassPath.EMPTY;
+ }
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/lookup/MavenProjectLookupProviderExtension.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/lookup/MavenProjectLookupProviderExtension.java
new file mode 100644
index 0000000..eeeaffa
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/lookup/MavenProjectLookupProviderExtension.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven.lookup;
+
+import org.jetbrains.kotlin.projectsextensions.KotlinPrivilegedTemplates;
+import org.jetbrains.kotlin.projectsextensions.maven.MavenProjectOpenedHook;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.LookupProvider;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class MavenProjectLookupProviderExtension implements LookupProvider {
+
+ @Override
+ public Lookup createAdditionalLookup(Lookup lkp) {
+ Project project = lkp.lookup(Project.class);
+
+ return Lookups.fixed(new KotlinPrivilegedTemplates(),
+ new MavenProjectOpenedHook(project)
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/output/KotlinMavenOutputProcessor.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/output/KotlinMavenOutputProcessor.kt
new file mode 100644
index 0000000..0ccfc8d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/output/KotlinMavenOutputProcessor.kt
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven.output
+
+import java.io.File
+import org.jetbrains.kotlin.navigation.netbeans.openFileAtPosition
+import org.netbeans.modules.maven.api.output.OutputProcessor
+import org.netbeans.modules.maven.api.output.OutputVisitor
+import org.openide.filesystems.FileObject
+import org.openide.filesystems.FileUtil
+import org.openide.windows.OutputEvent
+import org.openide.windows.OutputListener
+
+class KotlinMavenOutputProcessor : OutputProcessor {
+
+ override fun processLine(line: String, visitor: OutputVisitor) {
+ val fileName = line.substringBefore(":")
+ if (fileName == line) return
+
+ val file = File(fileName)
+ if (!file.exists()) return
+
+ val fo = FileUtil.toFileObject(FileUtil.normalizeFile(File(fileName))) ?: return
+ val colon = line.indexOf(":")
+
+ fun position(first: Char, second: Char): Pair<Int, Int>? {
+ val start = line.indexOf(first) + 1
+ val end = line.indexOf(second)
+ val split = if (first == '[') "," else ", "
+ val positions = line.substring(start, end).split(split)
+
+ if (positions.size != 2) return null
+
+ return Pair(positions[0].toInt(), positions[1].toInt())
+ }
+
+ val position = (if (line[colon + 1] == '[') position('[', ']') else position('(', ')')) ?: return
+
+ visitor.outputListener = CompilationErrorAnnotation(fo, position.first, position.second)
+ }
+
+ override fun getRegisteredOutputSequences() = arrayOf("mojo-execute#kotlin:compile",
+ "mojo-execute#kotlin:test-compile")
+
+ override fun sequenceFail(sequenceId: String?, visitor: OutputVisitor?) {}
+
+ override fun sequenceEnd(sequenceId: String?, visitor: OutputVisitor?) {}
+
+ override fun sequenceStart(sequenceId: String?, visitor: OutputVisitor?) {}
+}
+
+class CompilationErrorAnnotation(private val file: FileObject,
+ private val lineNumber: Int,
+ private val columnNumber: Int) : OutputListener {
+
+ override fun outputLineAction(event: OutputEvent) {
+ file.openFileAtPosition(lineNumber, columnNumber)
+ }
+
+ override fun outputLineSelected(event: OutputEvent?) {}
+
+ override fun outputLineCleared(event: OutputEvent?) {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/output/KotlinMavenOutputProcessorFactory.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/output/KotlinMavenOutputProcessorFactory.java
new file mode 100644
index 0000000..b526ff6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/output/KotlinMavenOutputProcessorFactory.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven.output;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.maven.api.execute.RunConfig;
+import org.netbeans.modules.maven.api.output.ContextOutputProcessorFactory;
+import org.netbeans.modules.maven.api.output.OutputProcessor;
+import org.netbeans.modules.maven.api.output.OutputProcessorFactory;
+import org.openide.util.lookup.ServiceProvider;
+
+@ServiceProvider(service=OutputProcessorFactory.class)
+public class KotlinMavenOutputProcessorFactory implements ContextOutputProcessorFactory {
+
+ @Override
+ public Set<OutputProcessor> createProcessorsSet(Project project) {
+ Set<OutputProcessor> toReturn = new HashSet<>();
+ if (project != null) {
+ toReturn.add(new KotlinMavenOutputProcessor());
+ }
+ return toReturn;
+ }
+
+ @Override
+ public Set<? extends OutputProcessor> createProcessorsSet(Project project, RunConfig config) {
+ return Collections.emptySet();
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/utils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/utils.kt
new file mode 100644
index 0000000..5a5ee34
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/projectsextensions/maven/utils.kt
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.projectsextensions.maven
+
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.utils.hasMain
+import org.jetbrains.kotlin.utils.mainClassName
+import org.netbeans.spi.project.ActionProvider
+import org.openide.filesystems.FileObject
+import org.openide.util.Lookup
+
+fun convert(action: String, lookup: Lookup): String? {
+ if (ActionProvider.COMMAND_RUN_SINGLE == action || ActionProvider.COMMAND_DEBUG_SINGLE == action) {
+ val f = lookup.lookup(FileObject::class.java)
+
+ if (f != null && "text/x-kt" == f.mimeType) {
+ val ktFile = ProjectUtils.getKtFile(f)
+ if (!ktFile.hasMain()) return null
+
+ return "$action.main"
+ }
+ }
+
+ return null;
+}
+
+fun createReplacements(action: String, lookup: Lookup): Map<String, String> {
+ val f = lookup.lookup(FileObject::class.java)
+
+ if (f != null && "text/x-kt" == f.mimeType) {
+ val ktFile = ProjectUtils.getKtFile(f) ?: return emptyMap()
+ val fqName = ktFile.mainClassName() ?: return emptyMap()
+
+ return mapOf("packageClassName" to fqName)
+ }
+
+ return emptyMap();
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinActionsImplementationProvider.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinActionsImplementationProvider.java
new file mode 100644
index 0000000..6824763
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinActionsImplementationProvider.java
@@ -0,0 +1,73 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.refactorings.rename;
+
+import com.intellij.psi.PsiElement;
+import javax.swing.JEditorPane;
+import javax.swing.text.StyledDocument;
+import org.jetbrains.kotlin.builder.KotlinPsiManager;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.modules.refactoring.api.RenameRefactoring;
+import org.netbeans.modules.refactoring.spi.ui.ActionsImplementationProvider;
+import org.netbeans.modules.refactoring.spi.ui.UI;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ServiceProvider;
+import org.openide.windows.TopComponent;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+@ServiceProvider(service = ActionsImplementationProvider.class, position = 400)
+public class KotlinActionsImplementationProvider extends ActionsImplementationProvider {
+
+ @Override
+ public boolean canRename(Lookup lookup) {
+ EditorCookie ec = lookup.lookup(EditorCookie.class);
+ if (ec == null) {
+ return false;
+ }
+ StyledDocument doc = ec.getDocument();
+ if (doc == null) {
+ return false;
+ }
+ FileObject fo = ProjectUtils.getFileObjectForDocument(doc);
+ return fo != null && fo.hasExt("kt");
+
+ }
+
+ @Override
+ public void doRename(Lookup lookup) {
+ EditorCookie ec = lookup.lookup(EditorCookie.class);
+ JEditorPane pane = ec.getOpenedPanes()[0];
+ int caretPosition = pane.getCaretPosition();
+ StyledDocument doc = ec.getDocument();
+ FileObject fo = ProjectUtils.getFileObjectForDocument(doc);
+ final KtFile ktFile = KotlinPsiManager.INSTANCE.getParsedFile(fo);
+ final PsiElement psi = ktFile.findElementAt(caretPosition);
+ UI.openRefactoringUI(new KotlinRenameRefactoringUI(psi, new RenameRefactoring(Lookups.fixed(psi, doc))),
+ TopComponent.getRegistry().getActivated());
+
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinInstantRenamer.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinInstantRenamer.kt
new file mode 100644
index 0000000..ea26281
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinInstantRenamer.kt
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.refactorings.rename
+
+import com.intellij.psi.search.LocalSearchScope
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.highlighter.occurrences.getKotlinElements
+import org.jetbrains.kotlin.highlighter.occurrences.getSearchingElements
+import org.jetbrains.kotlin.highlighter.occurrences.search
+import org.jetbrains.kotlin.navigation.references.resolveToSourceDeclaration
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtFile
+import org.netbeans.modules.csl.api.InstantRenamer
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.csl.spi.ParserResult
+
+class KotlinInstantRenamer : InstantRenamer {
+
+ private var occurrencesRanges: Set<OffsetRange>? = null
+
+ override fun getRenameRegions(info: ParserResult, caretOffset: Int) = occurrencesRanges ?: emptySet()
+
+ override fun isRenameAllowed(info: ParserResult, caretOffset: Int, explanationRetValue: Array<String>?): Boolean {
+ val fo = info.snapshot.source.fileObject
+
+ val ktFile = KotlinPsiManager.getParsedFile(fo) ?: return false
+ val psi = ktFile.findElementAt(caretOffset) ?: return false
+ val ktElement: KtElement = PsiTreeUtil.getNonStrictParentOfType(psi, KtElement::class.java) ?: return false
+
+ val sourceElements = ktElement.resolveToSourceDeclaration()
+ if (sourceElements.isEmpty()) return false
+
+ val searchingElements = getSearchingElements(sourceElements)
+ val searchKtElements = getKotlinElements(searchingElements)
+
+ if (searchKtElements.isEmpty()) return false
+ val searchingElement = searchKtElements.first()
+
+ if (psi.text.contains(" ") || psi.text == "interface"
+ || psi.text == "class" || psi.text == "fun"
+ || psi.text == "package") return false
+
+ if (searchingElement.useScope is LocalSearchScope) {
+ occurrencesRanges = search(searchingElements, psi.containingFile as KtFile).toSet()
+
+ return true
+ }
+
+ return false
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRefactoringElement.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRefactoringElement.java
new file mode 100644
index 0000000..3e760d7
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRefactoringElement.java
@@ -0,0 +1,91 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.refactorings.rename;
+
+import java.io.IOException;
+import javax.swing.text.BadLocationException;
+import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
+import org.openide.filesystems.FileObject;
+import org.openide.text.PositionBounds;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinRefactoringElement extends SimpleRefactoringElementImplementation {
+
+ private final String newName;
+ private final String oldName;
+ private final PositionBounds bounds;
+ private final FileObject fo;
+
+ public KotlinRefactoringElement(FileObject fo, String newName, String oldName, PositionBounds bounds) {
+ this.newName = newName;
+ this.oldName = oldName;
+ this.bounds = bounds;
+ this.fo = fo;
+ }
+
+ @Override
+ public String getText() {
+ return newName;
+ }
+
+ @Override
+ public String getDisplayText() {
+ return newName;
+ }
+
+ @Override
+ public void performChange() {
+ try {
+ bounds.setText(newName);
+ } catch (IOException | BadLocationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ @Override
+ public void undoChange() {
+ try {
+ bounds.setText(oldName);
+ } catch (IOException | BadLocationException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ @Override
+ public Lookup getLookup() {
+ return Lookups.fixed();
+ }
+
+ @Override
+ public FileObject getParentFile() {
+ return fo;
+ }
+
+ @Override
+ public PositionBounds getPosition() {
+ return bounds;
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRefactoringsFactory.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRefactoringsFactory.java
new file mode 100644
index 0000000..0cdf08b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRefactoringsFactory.java
@@ -0,0 +1,51 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.refactorings.rename;
+
+import javax.swing.text.StyledDocument;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.modules.refactoring.api.AbstractRefactoring;
+import org.netbeans.modules.refactoring.api.RenameRefactoring;
+import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
+import org.netbeans.modules.refactoring.spi.RefactoringPluginFactory;
+import org.openide.filesystems.FileObject;
+import org.openide.util.lookup.ServiceProvider;
+
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+@ServiceProvider(service = RefactoringPluginFactory.class, position = 100)
+public class KotlinRefactoringsFactory implements RefactoringPluginFactory {
+
+ @Override
+ public RefactoringPlugin createInstance(AbstractRefactoring refactoring) {
+ FileObject fo = ProjectUtils.getFileObjectForDocument(refactoring.getRefactoringSource().lookup(StyledDocument.class));
+ if (fo == null || !fo.hasExt("kt")) {
+ return null;
+ }
+ if (refactoring instanceof RenameRefactoring) {
+ return new KotlinRenameRefactoring((RenameRefactoring) refactoring);
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenamePanel.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenamePanel.java
new file mode 100644
index 0000000..702a5f8
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenamePanel.java
@@ -0,0 +1,120 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.refactorings.rename;
+
+import java.awt.Component;
+import javax.swing.JPanel;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinRenamePanel extends JPanel implements CustomRefactoringPanel {
+
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JLabel label;
+ private javax.swing.JTextField nameField;
+ private final transient String oldName;
+ private final transient ChangeListener parent;
+
+ public KotlinRenamePanel(String oldName, ChangeListener parent) {
+ this.oldName = oldName;
+ this.parent = parent;
+ initComponents();
+ nameField.setEnabled(true);
+ nameField.getDocument().addDocumentListener(new DocumentListener() {
+ @Override
+ public void changedUpdate(DocumentEvent event) {
+ KotlinRenamePanel.this.parent.stateChanged(null);
+ }
+ @Override
+ public void insertUpdate(DocumentEvent event) {
+ KotlinRenamePanel.this.parent.stateChanged(null);
+ }
+ @Override
+ public void removeUpdate(DocumentEvent event) {
+ KotlinRenamePanel.this.parent.stateChanged(null);
+ }
+ });
+ }
+
+ public String getNameValue() {
+ return nameField.getText();
+ }
+
+ private void initComponents() {
+ java.awt.GridBagConstraints gridBagConstraints;
+
+ label = new javax.swing.JLabel();
+ nameField = new javax.swing.JTextField();
+ jPanel1 = new javax.swing.JPanel();
+
+ setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 11, 11));
+ setLayout(new java.awt.GridBagLayout());
+
+ label.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
+ label.setLabelFor(nameField);
+ add(label, new java.awt.GridBagConstraints());
+
+ nameField.setText(oldName);
+ nameField.selectAll();
+ nameField.addFocusListener(new java.awt.event.FocusAdapter() {
+ @Override
+ public void focusLost(java.awt.event.FocusEvent evt) {
+ nameFieldFocusLost(evt);
+ }
+ });
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.weightx = 1.0;
+ add(nameField, gridBagConstraints);
+
+ jPanel1.setMinimumSize(new java.awt.Dimension(0, 0));
+ jPanel1.setPreferredSize(new java.awt.Dimension(0, 0));
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 3;
+ gridBagConstraints.gridwidth = 2;
+ gridBagConstraints.gridheight = 2;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.weighty = 1.0;
+ add(jPanel1, gridBagConstraints);
+
+ }
+
+
+ @Override
+ public void initialize() {
+ }
+
+ @Override
+ public Component getComponent() {
+ return this;
+ }
+
+ private void nameFieldFocusLost(java.awt.event.FocusEvent evt) {
+ parent.stateChanged(null);
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenameRefactoring.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenameRefactoring.kt
new file mode 100644
index 0000000..5ae98c9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenameRefactoring.kt
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.refactorings.rename
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiTreeUtil
+import javax.swing.text.StyledDocument
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtNamedFunction
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.modules.refactoring.api.Problem
+import org.netbeans.modules.refactoring.api.RenameRefactoring
+import org.netbeans.modules.refactoring.spi.ProgressProviderAdapter
+import org.netbeans.modules.refactoring.spi.RefactoringElementsBag
+import org.netbeans.modules.refactoring.spi.RefactoringPlugin
+
+class KotlinRenameRefactoring(val refactoring: RenameRefactoring) : ProgressProviderAdapter(), RefactoringPlugin {
+
+ override fun prepare(bag: RefactoringElementsBag): Problem? {
+ val newName = refactoring.newName
+ val fo = ProjectUtils.getFileObjectForDocument(refactoring.refactoringSource.lookup(StyledDocument::class.java)) ?: return null
+ val psi = refactoring.refactoringSource.lookup(PsiElement::class.java)
+
+ val renameMap = getRenameRefactoringMap(fo, psi, newName)
+ bag.registerTransaction(transaction(renameMap))
+ bag.session.doRefactoring(true)
+
+ return null
+ }
+
+ override fun checkParameters() = null
+
+ override fun preCheck(): Problem? {
+ val psi = refactoring.refactoringSource.lookup(PsiElement::class.java)
+ val ktElement: KtElement = PsiTreeUtil.getNonStrictParentOfType(psi, KtElement::class.java) ?: return null
+
+ if (ktElement !is KtClassOrObject
+ && ktElement !is KtNamedFunction
+ && ktElement !is KtProperty
+ && ktElement !is KtParameter) return Problem(true, "")
+
+ if (psi.text.contains(" ") || psi.text == "interface"
+ || psi.text == "class" || psi.text == "fun"
+ || psi.text == "package") return Problem(true, "")
+
+ return null
+ }
+
+ override fun fastCheckParameters() = null
+
+ override fun cancelRequest() {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenameRefactoringUI.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenameRefactoringUI.java
new file mode 100644
index 0000000..7f42b02
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/KotlinRenameRefactoringUI.java
@@ -0,0 +1,99 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.refactorings.rename;
+
+import com.intellij.psi.PsiElement;
+import javax.swing.event.ChangeListener;
+import org.netbeans.modules.refactoring.api.AbstractRefactoring;
+import org.netbeans.modules.refactoring.api.Problem;
+import org.netbeans.modules.refactoring.api.RenameRefactoring;
+import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
+import org.netbeans.modules.refactoring.spi.ui.RefactoringUI;
+import org.openide.util.HelpCtx;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class KotlinRenameRefactoringUI implements RefactoringUI {
+
+ private final String name = "Rename refactoring";
+ private final RenameRefactoring refactoring;
+ private final PsiElement psi;
+ private String newName;
+ private KotlinRenamePanel panel = null;
+
+ public KotlinRenameRefactoringUI(PsiElement psi, RenameRefactoring refactoring) {
+ this.psi = psi;
+ this.refactoring = refactoring;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ return name;
+ }
+
+ @Override
+ public boolean isQuery() {
+ return false;
+ }
+
+ @Override
+ public CustomRefactoringPanel getPanel(ChangeListener parent) {
+ if (panel == null) {
+ panel = new KotlinRenamePanel(psi.getText(), parent);
+ }
+ return panel;
+ }
+
+ @Override
+ public Problem setParameters() {
+ if (panel != null) {
+ newName = panel.getNameValue();
+ } else newName = psi.getText();
+ refactoring.setNewName(newName);
+ return null;
+ }
+
+ @Override
+ public Problem checkParameters() {
+ refactoring.fastCheckParameters();
+ return null;
+ }
+
+ @Override
+ public boolean hasParameters() {
+ return true;
+ }
+
+ @Override
+ public AbstractRefactoring getRefactoring() {
+ return refactoring;
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/TypeUsagesSearcher.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/TypeUsagesSearcher.kt
new file mode 100644
index 0000000..4719c0f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/TypeUsagesSearcher.kt
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.refactorings.rename
+
+import com.sun.source.tree.*
+import com.sun.source.util.TreePath
+import com.sun.source.util.TreePathScanner
+import javax.lang.model.element.Element
+import javax.lang.model.element.ExecutableElement
+import javax.lang.model.element.TypeElement
+import javax.lang.model.element.TypeParameterElement
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.java.source.CancellableTask
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.java.source.JavaSource
+import org.netbeans.modules.csl.api.OffsetRange
+
+class TypeUsagesSearcher(val toFind: ElementHandle<TypeElement>) : TreePathScanner<Tree, ElementHandle<*>>(),
+ CancellableTask<CompilationController> {
+
+ private lateinit var info: CompilationController
+ val usages = hashSetOf<OffsetRange>()
+
+ fun clearUsages() = usages.clear()
+
+ override fun cancel() {
+ }
+
+ override fun run(info: CompilationController) {
+ info.toPhase(JavaSource.Phase.RESOLVED)
+ this.info = info
+
+ val treePath = TreePath(info.compilationUnit)
+ scan(treePath, toFind)
+ }
+
+ override fun visitMethod(node: MethodTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitMethod(node, handle)
+ val el = info.trees.getElement(currentPath) as? ExecutableElement ?: return super.visitMethod(node, handle)
+
+ addUsageIfApplicable(e, { el.returnType == e.asType() }, { indexOf(it) })
+
+ return super.visitMethod(node, handle)
+ }
+
+ override fun visitVariable(node: VariableTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitVariable(node, handle)
+ val el = info.trees.getElement(currentPath) ?: return super.visitVariable(node, handle)
+
+ addUsageIfApplicable(e, { el.asType() == e.asType() }, { indexOf(it) })
+
+ return super.visitVariable(node, handle)
+ }
+
+ override fun visitNewClass(node: NewClassTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitNewClass(node, handle)
+ val el = info.trees.getElement(currentPath) ?: return super.visitNewClass(node, handle)
+
+ addUsageIfApplicable(e, { el.enclosingElement.asType() == e.asType() })
+
+ return super.visitNewClass(node, handle)
+ }
+
+ override fun visitTypeCast(node: TypeCastTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitTypeCast(node, handle)
+
+ addUsageIfApplicable(e, { it.substring(1, it.indexOf(")")).endsWith(e.simpleName) })
+
+ return super.visitTypeCast(node, handle)
+ }
+
+ override fun visitInstanceOf(node: InstanceOfTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info)
+
+ addUsageIfApplicable(e, { it.substringAfterLast(" ").endsWith(e.simpleName) })
+
+ return super.visitInstanceOf(node, handle)
+ }
+
+ override fun visitImport(node: ImportTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) as? TypeElement ?: return super.visitImport(node, handle)
+
+ addUsageIfApplicable(e, { it.endsWith("${e.qualifiedName};") })
+
+ return super.visitImport(node, handle)
+ }
+
+ override fun visitClass(node: ClassTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitClass(node, handle)
+ val el = info.trees.getElement(currentPath) as? TypeElement ?: return super.visitClass(node, handle)
+
+ addUsageIfApplicable(e, { el.interfaces.contains(e.asType()) || el.superclass == e.asType() })
+
+ return super.visitClass(node, handle)
+ }
+
+ override fun visitTypeParameter(node: TypeParameterTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitTypeParameter(node, handle)
+ val el = info.trees.getElement(currentPath) as? TypeParameterElement ?: return super.visitTypeParameter(node, handle)
+
+ addUsageIfApplicable(e, { el.bounds.contains(e.asType()) })
+
+ return super.visitTypeParameter(node, handle)
+ }
+
+ override fun visitParameterizedType(node: ParameterizedTypeTree?, handle: ElementHandle<*>): Tree? {
+ val e = handle.resolve(info) ?: return super.visitParameterizedType(node, handle)
+
+ addUsageIfApplicable(e, { currentPath.leaf.toString().contains(e.simpleName) })
+
+ return super.visitParameterizedType(node, handle)
+ }
+
+ private fun addUsageIfApplicable(e: Element,
+ condition: (String) -> Boolean,
+ index: String.(String) -> Int = { lastIndexOf(it) }) {
+ val start = info.trees.sourcePositions.
+ getStartPosition(info.compilationUnit, currentPath.leaf).toInt()
+ val end = info.trees.sourcePositions.
+ getEndPosition(info.compilationUnit, currentPath.leaf).toInt()
+
+ if (end - start <= 0) return
+
+ val doc = ProjectUtils.getDocumentFromFileObject(info.fileObject) ?: return
+ val text = doc.getText(start, end - start)
+
+ if (condition(text)) {
+ val startIndex = start + text.index(e.simpleName.toString())
+ val endIndex = startIndex + e.simpleName.toString().length
+
+ usages.add(OffsetRange(startIndex, endIndex))
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/renameUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/renameUtils.kt
new file mode 100644
index 0000000..92dda83
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/refactorings/rename/renameUtils.kt
@@ -0,0 +1,245 @@
+@file:JvmName("RenamePerformer")
+
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.refactorings.rename
+
+import com.intellij.psi.PsiElement
+import com.intellij.psi.search.LocalSearchScope
+import com.intellij.psi.util.PsiTreeUtil
+import java.io.File
+import javax.swing.text.Position
+import org.jetbrains.kotlin.fileClasses.*
+import org.jetbrains.kotlin.highlighter.occurrences.*
+import org.jetbrains.kotlin.navigation.references.resolveToSourceDeclaration
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.*
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.java.source.*
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.csl.spi.GsfUtilities
+import org.netbeans.modules.refactoring.java.api.JavaRefactoringUtils
+import org.openide.filesystems.FileObject
+import org.openide.filesystems.FileUtil
+import org.openide.text.PositionBounds
+import org.netbeans.modules.csl.spi.support.ModificationResult
+import org.netbeans.modules.csl.spi.support.ModificationResult.Difference
+import org.netbeans.modules.refactoring.spi.Transaction
+import org.netbeans.modules.refactoring.spi.RefactoringCommit
+
+/*
+ @author Alexander.Baratynski
+ Created on Sep 13, 2016
+*/
+
+fun getRenameRefactoringMap(fo: FileObject, psi: PsiElement, newName: String): Map<FileObject, Map<OffsetRange, String>> {
+ val ranges = hashMapOf<FileObject, Map<OffsetRange, String>>()
+
+ val ktElement: KtElement = PsiTreeUtil.getNonStrictParentOfType(psi, KtElement::class.java) ?: return ranges
+
+ val sourceElements = ktElement.resolveToSourceDeclaration()
+ if (sourceElements.isEmpty()) return ranges
+
+ val searchingElements = getSearchingElements(sourceElements)
+ val project = ProjectUtils.getKotlinProjectForFileObject(fo) ?: return ranges
+
+ val searchKtElements = getKotlinElements(searchingElements)
+
+ if (searchKtElements.isEmpty()) return ranges
+ val searchingElement = searchKtElements.first()
+
+ if (searchingElement.useScope is LocalSearchScope) {
+ val occurrencesRanges = search(searchingElements, psi.containingFile as KtFile)
+ if (occurrencesRanges.isNotEmpty()) {
+ ranges.put(fo, occurrencesRanges.associate { Pair(it, newName) })
+ }
+
+ return ranges
+ }
+
+ ranges.putAll(getJavaRefactoringMap(searchingElement, project, newName))
+
+ ProjectUtils.getSourceFiles(project).forEach {
+ val occurrencesRanges = search(searchingElement, it)
+ val f = File(it.virtualFile.path)
+ val file = FileUtil.toFileObject(f)
+ if (file != null && occurrencesRanges.isNotEmpty()) {
+ ranges.put(file, occurrencesRanges.associate { Pair(it, newName) })
+ }
+ }
+
+ return ranges
+}
+
+private fun getJavaRefactoringMap(searchingElement: KtElement,
+ project: Project,
+ newName: String): Map<FileObject, Map<OffsetRange, String>> {
+ val refactoringMap = hashMapOf<FileObject, Map<OffsetRange, String>>()
+
+ fun addToRefactoringMap(file: FileObject, range: OffsetRange, newName: String) {
+ if (refactoringMap.containsKey(file)) {
+ val map = hashMapOf<OffsetRange, String>()
+ map.put(range, newName)
+ map.putAll(refactoringMap[file]!!)
+ refactoringMap.put(file, map)
+ } else refactoringMap.put(file, mapOf(Pair(range, newName)))
+ }
+
+ when (searchingElement) {
+ is KtClassOrObject -> getJavaRefactoringMapForClassOrObject(searchingElement, project,
+ newName, ::addToRefactoringMap)
+ is KtNamedFunction -> getJavaRefactoringMapForNamedFunction(searchingElement, project,
+ newName, ::addToRefactoringMap)
+ is KtProperty -> getJavaRefactoringMapForProperty(searchingElement, project,
+ newName, ::addToRefactoringMap)
+ }
+
+ return refactoringMap
+}
+
+private fun getJavaRefactoringMapForProperty(searchingElement: KtProperty,
+ project: Project,
+ newName: String,
+ addToRefactoringMap: (FileObject, OffsetRange, String) -> Unit) {
+ val name = searchingElement.name ?: return
+
+ val getterName = "get${name.capitalize()}"
+ val setterName = "set${name.capitalize()}"
+
+ val newGetterName = "get${newName.capitalize()}"
+ val newSetterName = "set${newName.capitalize()}"
+
+ val getter = getClassMethod(searchingElement, project, getterName)
+ val setter = getClassMethod(searchingElement, project, setterName, 1)
+
+ addMemberUsagesToRefactoringMap(getter, project, newGetterName, addToRefactoringMap)
+ addMemberUsagesToRefactoringMap(setter, project, newSetterName, addToRefactoringMap)
+}
+
+private fun getJavaRefactoringMapForClassOrObject(searchingElement: KtClassOrObject,
+ project: Project,
+ newName: String,
+ addToRefactoringMap: (FileObject, OffsetRange, String) -> Unit) {
+ val fqName = searchingElement.fqName ?: return
+ val elementHandle = project.findTypeElementHandle(fqName.asString()) ?: return
+
+ val references = JavaEnvironment.JAVA_SOURCE[project]!!.classpathInfo.
+ classIndex.getResources(elementHandle,
+ searchKinds(),
+ setOf(ClassIndex.SearchScope.SOURCE))
+
+ val usagesSearcher = TypeUsagesSearcher(elementHandle)
+
+ references.forEach {
+ JavaSource.forFileObject(it).runUserActionTask(usagesSearcher, true)
+ usagesSearcher.usages.forEach { usage ->
+ addToRefactoringMap(it, usage, newName)
+ }
+ usagesSearcher.clearUsages()
+ }
+}
+
+private fun getJavaRefactoringMapForNamedFunction(searchingElement: KtNamedFunction,
+ project: Project,
+ newName: String,
+ addToRefactoringMap: (FileObject, OffsetRange, String) -> Unit) {
+ val methodName = searchingElement.name ?: return
+ val numberOfValueParameters = searchingElement.valueParameters.size
+
+ val method = getClassMethod(searchingElement, project, methodName, numberOfValueParameters)
+
+ addMemberUsagesToRefactoringMap(method, project, newName, addToRefactoringMap)
+}
+
+private fun addMemberUsagesToRefactoringMap(method: ElementHandle<*>?,
+ project: Project,
+ newName: String,
+ addToRefactoringMap: (FileObject, OffsetRange, String) -> Unit) {
+ if (method == null) return
+
+ JavaEnvironment.checkJavaSource(project)
+ JavaEnvironment.JAVA_SOURCE[project]!!.runUserActionTask({
+ it.toPhase(JavaSource.Phase.RESOLVED)
+
+ JavaRefactoringUtils.getInvocationsOf(method, it)
+ .forEach { handle ->
+ val file = handle.fileObject
+ JavaSource.forFileObject(file).runUserActionTask({ fileCC ->
+ val treePath = handle.resolve(fileCC)
+ val start = fileCC.trees.sourcePositions.
+ getStartPosition(fileCC.compilationUnit, treePath.leaf)
+ val end = fileCC.trees.sourcePositions.
+ getEndPosition(fileCC.compilationUnit, treePath.leaf)
+
+ val range = getOffsetOfMethodInvocation(file, start.toInt(), end.toInt())
+ if (range != null) {
+ addToRefactoringMap(file, range, newName)
+ }
+ }, true)
+ }
+ }, true)
+}
+
+private fun getClassMethod(searchingElement: KtDeclaration,
+ project: Project,
+ methodName: String,
+ numberOfValueParameters: Int = 0): ElementHandle<*>? {
+ val classOrObject = searchingElement.containingClassOrObject?.fqName ?:
+ NoResolveFileClassesProvider.getFileClassFqName(searchingElement.containingKtFile)
+ val elementHandle = project.findTypeElementHandle(classOrObject.asString()) ?: return null
+ val methods = elementHandle.getMethodsHandles(project)
+
+ return methods.filter { it.getName(project).toString() == methodName }
+ .firstOrNull { it.getElementHandleValueParameters(project).size == numberOfValueParameters } ?: return null
+}
+
+private fun getOffsetOfMethodInvocation(fo: FileObject,
+ start: Int,
+ end: Int): OffsetRange? {
+ val doc = ProjectUtils.getDocumentFromFileObject(fo) ?: return null
+ val text = doc.getText(start, end - start)
+
+ val startIndex = text.lastIndexOf(".") + 1
+
+ return OffsetRange(start + startIndex, end)
+}
+
+fun createPositionBoundsForFO(fo: FileObject, ranges: Map<OffsetRange, String>): List<Pair<PositionBounds,String>> {
+ val ces = GsfUtilities.findCloneableEditorSupport(fo) ?: return emptyList()
+
+ return ranges.map {
+ Pair(
+ PositionBounds(
+ ces.createPositionRef(it.key.start, Position.Bias.Forward),
+ ces.createPositionRef(it.key.end, Position.Bias.Forward)
+ ),
+ it.value
+ )
+ }
+}
+
+fun transaction(renameMap: Map<FileObject, Map<OffsetRange, String>>): Transaction {
+ val result = ModificationResult()
+ for ((file, rangeAndName) in renameMap) {
+ val posBounds = createPositionBoundsForFO(file, rangeAndName)
+ result.addDifferences(file, posBounds.map { Difference(Difference.Kind.CHANGE, it.first.begin, it.first.end, "", it.second) })
+ }
+
+ return RefactoringCommit(listOf(result))
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/KotlinReformatTask.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/KotlinReformatTask.kt
new file mode 100644
index 0000000..5bfe3f7
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/KotlinReformatTask.kt
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.reformatting
+
+import org.netbeans.modules.editor.indent.spi.Context
+import org.netbeans.modules.editor.indent.spi.ReformatTask
+
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 9, 2016
+*/
+
+class KotlinReformatTask(val context : Context) : ReformatTask {
+
+ override fun reformat() = format(context.document(), context.caretOffset())
+
+ override fun reformatLock() = null
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/KotlinReformatTaskFactory.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/KotlinReformatTaskFactory.java
new file mode 100644
index 0000000..dc4b79f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/KotlinReformatTaskFactory.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.reformatting;
+
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.modules.editor.indent.spi.Context;
+import org.netbeans.modules.editor.indent.spi.ReformatTask;
+
+@MimeRegistration(mimeType="text/x-kt",service=ReformatTask.Factory.class)
+public class KotlinReformatTaskFactory implements ReformatTask.Factory {
+
+ @Override
+ public ReformatTask createTask(Context context) {
+ return new KotlinReformatTask(context);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/formatUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/formatUtils.kt
new file mode 100644
index 0000000..4dafbca
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/reformatting/formatUtils.kt
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.reformatting
+
+import javax.swing.text.Document
+import org.jetbrains.kotlin.formatting.KotlinFormatterUtils
+import org.jetbrains.kotlin.navigation.netbeans.moveCaretToOffset
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.Project
+import javax.swing.text.StyledDocument
+import javax.swing.SwingUtilities
+
+
+fun format(doc: Document, offset: Int, proj: Project? = null) {
+ val file = ProjectUtils.getFileObjectForDocument(doc) ?: return
+
+ val parsedFile = ProjectUtils.getKtFile(doc.getText(0, doc.length), file) ?: return
+
+ val project = proj ?: ProjectUtils.getKotlinProjectForFileObject(file)
+ val code = parsedFile.text
+ val formattedCode = KotlinFormatterUtils.formatCode(code, parsedFile.name, project, "\n")
+ doc.remove(0, doc.length)
+ doc.insertString(0, formattedCode, null)
+ doc.moveCursorTo(offset)
+}
+
+fun Document.moveCursorTo(position: Int) = SwingUtilities.invokeLater { moveCaretToOffset(this as StyledDocument, position) }
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/AnalysisResultWithProvider.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/AnalysisResultWithProvider.kt
new file mode 100644
index 0000000..721581c
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/AnalysisResultWithProvider.kt
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve
+
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.container.ComponentProvider
+
+data class AnalysisResultWithProvider(val analysisResult: AnalysisResult,
+ val componentProvider: ComponentProvider)
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/BuiltInsReferenceResolver.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/BuiltInsReferenceResolver.java
new file mode 100644
index 0000000..a38bb7a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/BuiltInsReferenceResolver.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve;
+
+import com.google.common.collect.Sets;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.kotlin.builtins.DefaultBuiltIns;
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
+import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
+import org.jetbrains.kotlin.context.ContextKt;
+import org.jetbrains.kotlin.context.MutableModuleContext;
+import org.jetbrains.kotlin.descriptors.ClassDescriptor;
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
+import org.jetbrains.kotlin.descriptors.MemberDescriptor;
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
+import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
+import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
+import org.jetbrains.kotlin.frontend.di.InjectionKt;
+import org.jetbrains.kotlin.name.Name;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.jetbrains.kotlin.renderer.DescriptorRenderer;
+import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
+import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
+import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
+import org.jetbrains.kotlin.resolve.scopes.MemberScope;
+import org.jetbrains.kotlin.serialization.deserialization.FindClassInModuleKt;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsBundle;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.io.URLUtil;
+
+import kotlin.collections.CollectionsKt;
+import org.jetbrains.kotlin.model.KotlinEnvironment;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+
+public class BuiltInsReferenceResolver {
+ private static final String RUNTIME_SRC_DIR =
+ "jar:file:"+ ProjectUtils.buildLibPath("kotlin-runtime-sources")+ "!/kotlin";
+
+ private volatile ModuleDescriptor moduleDescriptor;
+ private volatile PackageFragmentDescriptor builtinsPackageFragment = null;
+ private final Project myProject;
+
+ public BuiltInsReferenceResolver(Project project) {
+ myProject = project;
+ initialize();
+ }
+
+ @NotNull
+ public static BuiltInsReferenceResolver getInstance(@NotNull org.netbeans.api.project.Project kotlinProject) {
+ Project ideaProject = KotlinEnvironment.Companion.getEnvironment(kotlinProject).getProject();
+ return ServiceManager.getService(ideaProject, BuiltInsReferenceResolver.class);
+ }
+
+ private void initialize() {
+ if (!areSourcesExist()) {
+ return;
+ }
+
+ Set<KtFile> ktBuiltInsFiles = getBuiltInSourceFiles();
+
+ //if the sources are present, then the value cannot be null
+ assert (ktBuiltInsFiles != null);
+
+ MutableModuleContext newModuleContext = ContextKt.ContextForNewModule(
+ ContextKt.ProjectContext(myProject),
+ Name.special("<built-ins resolver module>"),
+ DefaultBuiltIns.getInstance(),
+ null);
+ newModuleContext.setDependencies(newModuleContext.getModule());
+
+ FileBasedDeclarationProviderFactory declarationFactory = new FileBasedDeclarationProviderFactory(
+ newModuleContext.getStorageManager(), ktBuiltInsFiles);
+
+ ResolveSession resolveSession = InjectionKt.createLazyResolveSession(
+ newModuleContext, declarationFactory,
+ new BindingTraceContext(), TargetPlatform.Default.INSTANCE,
+ LanguageVersionSettingsImpl.DEFAULT);
+
+ newModuleContext.initializeModuleContents(resolveSession.getPackageFragmentProvider());
+
+ PackageViewDescriptor packageView = newModuleContext.getModule().getPackage(
+ KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME);
+ List<PackageFragmentDescriptor> fragments = packageView.getFragments();
+
+ moduleDescriptor = newModuleContext.getModule();
+ builtinsPackageFragment = CollectionsKt.single(fragments);
+ }
+
+ @Nullable
+ public Set<KtFile> getBuiltInSourceFiles() {
+ URL url;
+ try {
+ url = new URL(RUNTIME_SRC_DIR);
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ VirtualFile vf = getSourceVirtualFile();
+ assert vf != null : "Virtual file not found by URL: " + url;
+
+ PsiDirectory psiDirectory = PsiManager.getInstance(myProject).findDirectory(vf);
+ assert psiDirectory != null : "No PsiDirectory for " + vf;
+ return new HashSet<>(ContainerUtil.mapNotNull(psiDirectory.getFiles(), new Function<PsiFile, KtFile>() {
+ @Override
+ public KtFile fun(PsiFile file) {
+ return file instanceof KtFile ? (KtFile) file : null;
+ }
+ }));
+ }
+
+ private void addFilesFromFolder(Set<KtFile> files, VirtualFile root){
+
+ for (VirtualFile child : root.getChildren()){
+ if (child.isDirectory()){
+ addFilesFromFolder(files, child);
+ }
+ }
+
+ PsiDirectory psiDirectory = PsiManager.getInstance(myProject).findDirectory(root);
+ assert psiDirectory != null : "No PsiDirectory for " + root;
+ files.addAll(ContainerUtil.mapNotNull(psiDirectory.getFiles(), new Function<PsiFile, KtFile>() {
+ @Override
+ public KtFile fun(PsiFile file) {
+ return file instanceof KtFile ? (KtFile) file : null;
+ }
+ }));
+
+ }
+
+ public Set<KtFile> getAllFilesInKotlinSourceJar(){
+ Set<KtFile> files = Sets.newHashSet();
+ VirtualFile runtimeSrc = getSourceVirtualFile();
+
+ addFilesFromFolder(files, runtimeSrc);
+
+ return files;
+ }
+
+ @Nullable
+ private VirtualFile getSourceVirtualFile() {
+ URL runtimeUrl;
+ try {
+ runtimeUrl = new URL(RUNTIME_SRC_DIR);
+ String fromUrl = convertPathFromURL(runtimeUrl);
+ return VirtualFileManager.getInstance().findFileByUrl(fromUrl);
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ private boolean areSourcesExist() {
+ return getSourceVirtualFile() != null;
+ }
+
+ //the method is a copy of com.intellij.openapi.vfs.VfsUtilCore.convertFromUrl(URL)
+ private String convertPathFromURL(URL url) {
+ String protocol = url.getProtocol();
+ String path = url.getPath();
+ if (protocol.equals("jar")) {
+ if (StringUtil.startsWithConcatenation(path, "file", ":")) {
+ try {
+ URL subURL = new URL(path);
+ path = subURL.getPath();
+ }
+ catch (MalformedURLException e) {
+ throw new RuntimeException(VfsBundle.message("url.parse.unhandled.exception"), e);
+ }
+ }
+ else {
+ throw new RuntimeException(new IOException(VfsBundle.message("url.parse.error", url.toExternalForm())));
+ }
+ }
+ if (SystemInfo.isWindows || SystemInfo.isOS2) {
+ while (!path.isEmpty() && path.charAt(0) == '/') {
+ path = path.substring(1, path.length());
+ }
+ }
+
+ path = URLUtil.unescapePercentSequences(path);
+ String fromUrl = protocol + "://" + path;
+ return fromUrl;
+ }
+
+ @Nullable
+ private DeclarationDescriptor findCurrentDescriptorForMember(@NotNull MemberDescriptor originalDescriptor) {
+ DeclarationDescriptor containingDeclaration = findCurrentDescriptor(originalDescriptor.getContainingDeclaration());
+ MemberScope memberScope = getMemberScope(containingDeclaration);
+ if (memberScope == null) return null;
+
+ String renderedOriginal = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(originalDescriptor);
+ Collection<? extends DeclarationDescriptor> descriptors;
+ if (originalDescriptor instanceof ConstructorDescriptor && containingDeclaration instanceof ClassDescriptor) {
+ descriptors = ((ClassDescriptor) containingDeclaration).getConstructors();
+ }
+ else {
+ descriptors = memberScope.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.getALL_NAME_FILTER());
+ }
+ for (DeclarationDescriptor member : descriptors) {
+ if (renderedOriginal.equals(DescriptorRenderer.FQ_NAMES_IN_TYPES.render(member))) {
+ return member;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ public DeclarationDescriptor findCurrentDescriptor(@NotNull DeclarationDescriptor originalDescriptor) {
+ //if there's no sources
+ if (moduleDescriptor == null) {
+ return null;
+ }
+
+ if (!isFromBuiltinModule(originalDescriptor)) {
+ return null;
+ }
+
+ if (originalDescriptor instanceof ClassDescriptor) {
+ return FindClassInModuleKt.findClassAcrossModuleDependencies(
+ moduleDescriptor,
+ DescriptorUtilsKt.getClassId((ClassDescriptor) originalDescriptor));
+ }
+
+ if (originalDescriptor instanceof PackageFragmentDescriptor) {
+ return KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME.equals(((PackageFragmentDescriptor) originalDescriptor).getFqName())
+ ? builtinsPackageFragment
+ : null;
+ }
+
+ if (originalDescriptor instanceof MemberDescriptor) {
+ return findCurrentDescriptorForMember((MemberDescriptor) originalDescriptor);
+ }
+
+ return null;
+ }
+
+ public static boolean isFromBuiltinModule(@NotNull DeclarationDescriptor originalDescriptor) {
+ ModuleDescriptor module = DescriptorUtilsKt.getModule(originalDescriptor);
+ KotlinBuiltIns builtIns = module.getBuiltIns();
+ return module.equals(builtIns.getBuiltInsModule());
+ }
+
+ @Nullable
+ private static MemberScope getMemberScope(@Nullable DeclarationDescriptor parent) {
+ if (parent instanceof ClassDescriptor) {
+ return ((ClassDescriptor) parent).getDefaultType().getMemberScope();
+ }
+ else if (parent instanceof PackageFragmentDescriptor) {
+ return ((PackageFragmentDescriptor) parent).getMemberScope();
+ }
+ else {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/DeserializedDescriptorUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/DeserializedDescriptorUtils.kt
new file mode 100644
index 0000000..222fd84
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/DeserializedDescriptorUtils.kt
@@ -0,0 +1,17 @@
+package org.jetbrains.kotlin.resolve
+
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
+import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
+import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
+import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+
+fun isDeserialized(descriptor: DeclarationDescriptor) =
+ descriptor is DeserializedCallableMemberDescriptor || descriptor is DeserializedClassDescriptor
+
+fun getContainingClassOrPackage(descriptor: DeclarationDescriptor) =
+ descriptor.parentsWithSelf.firstOrNull() {
+ (it is ClassDescriptor && DescriptorUtils.isTopLevelDeclaration(it)) ||
+ it is PackageFragmentDescriptor
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinAnalyzer.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinAnalyzer.kt
new file mode 100644
index 0000000..81296b5
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinAnalyzer.kt
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve
+
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.psi.KtFile
+import org.netbeans.api.project.Project
+
+object KotlinAnalyzer {
+
+ fun analyzeFile(project: Project, file: KtFile): AnalysisResultWithProvider {
+ KotlinLogger.INSTANCE.logInfo("Analyzing ${file.virtualFile.path}")
+ val kotlinEnvironment = KotlinEnvironment.getEnvironment(project)
+
+ return NetBeansAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
+ project, kotlinEnvironment.project, listOf(file))
+ }
+
+ private fun analyzeFiles(kotlinProject: Project,
+ kotlinEnvironment: KotlinEnvironment,
+ filesToAnalyze: Collection<KtFile>) = NetBeansAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(kotlinProject, kotlinEnvironment.project, filesToAnalyze)
+
+ fun analyzeFiles(kotlinProject: Project,
+ filesToAnalyze: Collection<KtFile>): AnalysisResultWithProvider {
+ if (filesToAnalyze.size == 1) return analyzeFile(kotlinProject, filesToAnalyze.iterator().next())
+
+ val kotlinEnvironment = KotlinEnvironment.getEnvironment(kotlinProject)
+ return analyzeFiles(kotlinProject, kotlinEnvironment, filesToAnalyze)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinCacheServiceImpl.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinCacheServiceImpl.kt
new file mode 100644
index 0000000..89c410b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinCacheServiceImpl.kt
@@ -0,0 +1,85 @@
+package org.jetbrains.kotlin.resolve
+
+import com.intellij.psi.PsiFile
+import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import com.intellij.openapi.project.Project
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
+import org.jetbrains.kotlin.container.ComponentProvider
+import org.netbeans.api.project.Project as NBProject
+
+class KotlinCacheServiceImpl(private val ideaProject: Project, val project: NBProject) : KotlinCacheService {
+
+ override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getSuppressionCache(): KotlinSuppressCache {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade =
+ KotlinSimpleResolutionFacade(ideaProject, elements, project)
+}
+
+class KotlinSimpleResolutionFacade(
+ override val project: Project,
+ private val elements: List<KtElement>,
+ private val nbProject: NBProject) : ResolutionFacade {
+
+ override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext {
+ if (elements.isEmpty()) {
+ return BindingContext.EMPTY
+ }
+ val ktFile = elements.first().containingKtFile
+ return KotlinParser.getAnalysisResult(ktFile, nbProject)?.analysisResult?.bindingContext ?: BindingContext.EMPTY
+ }
+
+ override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor {
+ throw UnsupportedOperationException()
+ }
+
+ override val moduleDescriptor: ModuleDescriptor
+ get() = throw UnsupportedOperationException()
+
+ override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext {
+ val ktFile = element.containingKtFile
+ return KotlinParser.getAnalysisResult(ktFile, nbProject)?.analysisResult?.bindingContext ?: BindingContext.EMPTY
+ }
+
+ override fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getFrontendService(serviceClass: Class<T>): T {
+ val files = elements.map { it.containingKtFile }.toSet()
+ if (files.isEmpty()) throw IllegalStateException("Elements should not be empty")
+
+ val componentProvider = KotlinAnalyzer.analyzeFiles(nbProject, files).componentProvider
+
+ return componentProvider.getService(serviceClass)
+ }
+
+ override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+
+ override fun <T : Any> getIdeService(serviceClass: Class<T>): T {
+ throw UnsupportedOperationException()
+ }
+}
+
+@Suppress("UNCHECKED_CAST") fun <T : Any> ComponentProvider.getService(request: Class<T>): T =
+ resolve(request)!!.getValue() as T
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinPackagePartProvider.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinPackagePartProvider.kt
new file mode 100644
index 0000000..3993a80
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinPackagePartProvider.kt
@@ -0,0 +1,88 @@
+package org.jetbrains.kotlin.resolve
+
+import com.intellij.openapi.vfs.VirtualFile
+import java.io.EOFException
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.descriptors.PackagePartProvider
+import org.jetbrains.kotlin.load.kotlin.ModuleMapping
+import org.jetbrains.kotlin.load.kotlin.PackageParts
+import org.jetbrains.kotlin.utils.SmartList
+
+class KotlinPackagePartProvider(val project: Project) : PackagePartProvider {
+ private data class ModuleMappingInfo(val root: VirtualFile, val mapping: ModuleMapping)
+
+ private val notLoadedRoots by lazy(LazyThreadSafetyMode.NONE) {
+ KotlinEnvironment.getEnvironment(project).roots
+ .map { it.file }
+ .filter { it.findChild("META-INF") != null }
+ .toMutableList()
+ }
+
+ private val loadedModules: MutableList<ModuleMappingInfo> = SmartList()
+
+ override fun findPackageParts(packageFqName: String): List<String> {
+ val rootToPackageParts = getPackageParts(packageFqName)
+ if (rootToPackageParts.isEmpty()) return emptyList()
+
+ val result = linkedSetOf<String>()
+ val visitedMultifileFacades = linkedSetOf<String>()
+ for ((_, packageParts) in rootToPackageParts) {
+ for (name in packageParts.parts) {
+ val facadeName = packageParts.getMultifileFacadeName(name)
+ if (facadeName == null || facadeName !in visitedMultifileFacades) {
+ result.add(name)
+ }
+ }
+ packageParts.parts.mapNotNullTo(visitedMultifileFacades) { packageParts.getMultifileFacadeName(it) }
+ }
+
+ return result.toList()
+ }
+
+ override fun findMetadataPackageParts(packageFqName: String) = getPackageParts(packageFqName).values
+ .flatMap(PackageParts::metadataParts)
+ .distinct()
+
+ @Synchronized private fun getPackageParts(packageFqName: String): Map<VirtualFile, PackageParts> {
+ processNotLoadedRelevantRoots(packageFqName)
+
+ val result = mutableMapOf<VirtualFile, PackageParts>()
+ for ((root, mapping) in loadedModules) {
+ val newParts = mapping.findPackageParts(packageFqName) ?: continue
+ result[root]?.let{ parts -> parts += newParts } ?: result.put(root, newParts)
+ }
+
+ return result
+ }
+
+ private fun processNotLoadedRelevantRoots(packageFqName: String) {
+ if (notLoadedRoots.isEmpty()) return
+
+ val pathParts = packageFqName.split('.')
+ val relevantRoots = notLoadedRoots.filter {
+ pathParts.fold(it) { parent, part ->
+ if (part.isEmpty()) parent
+ else parent.findChild(part) ?: return@filter false
+ }
+ true
+ }
+ notLoadedRoots.removeAll(relevantRoots)
+
+ for (root in relevantRoots) {
+ val metaInf = root.findChild("META-INF") ?: continue
+ val moduleFiles = metaInf.children.filter { it.name.endsWith(ModuleMapping.MAPPING_FILE_EXT) }
+ for (moduleFile in moduleFiles) {
+ val mapping = try {
+ if (!moduleFile.isValid) continue
+ ModuleMapping.create(moduleFile.contentsToByteArray(), moduleFile.toString())
+ }
+ catch (e: EOFException) {
+ throw RuntimeException("Error on reading package parts for '$packageFqName' package in '$moduleFile', roots: $notLoadedRoots", e)
+ }
+ loadedModules.add(ModuleMappingInfo(root, mapping))
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinResolutionFacade.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinResolutionFacade.kt
new file mode 100644
index 0000000..c6b59ca
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinResolutionFacade.kt
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.container.ComponentProvider
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
+import org.jetbrains.kotlin.container.getService
+import org.netbeans.api.project.Project as NBProject
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 9, 2016
+*/
+
+class KotlinResolutionFacade(private val kotlinProject: NBProject,
+ private val componentProvider: ComponentProvider,
+ override val moduleDescriptor: ModuleDescriptor) : ResolutionFacade {
+ override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode) = throw UnsupportedOperationException()
+
+
+ override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode) = throw UnsupportedOperationException()
+
+ override val project: Project
+ get() = KotlinEnvironment.getEnvironment(kotlinProject).project
+
+ override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext = throw UnsupportedOperationException()
+
+ override fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult = throw UnsupportedOperationException()
+
+ override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T = throw UnsupportedOperationException()
+
+ override fun <T : Any> getFrontendService(serviceClass: Class<T>): T = componentProvider.getService(serviceClass)
+
+ override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T = throw UnsupportedOperationException()
+
+ override fun <T : Any> getIdeService(serviceClass: Class<T>): T = throw UnsupportedOperationException()
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinSourceIndex.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinSourceIndex.kt
new file mode 100644
index 0000000..74a3332
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/KotlinSourceIndex.kt
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 9, 2016
+*/
+
+class KotlinSourceIndex
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/NetBeansAnalyzerFacadeForJVM.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/NetBeansAnalyzerFacadeForJVM.kt
new file mode 100644
index 0000000..48e7d5a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/NetBeansAnalyzerFacadeForJVM.kt
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analyzer.AnalysisResult
+import org.jetbrains.kotlin.builtins.JvmBuiltInsPackageFragmentProvider
+import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
+import org.jetbrains.kotlin.config.CommonConfigurationKeys
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
+import org.jetbrains.kotlin.context.MutableModuleContext
+import org.jetbrains.kotlin.context.ProjectContext
+import org.jetbrains.kotlin.util.KotlinFrontEndException
+import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
+import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.context.ContextForNewModule
+import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.platform.JvmBuiltIns
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
+import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
+import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM.SourceOrBinaryModuleClassResolver
+import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
+import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
+import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
+import org.jetbrains.kotlin.descriptors.impl.ModuleDependenciesImpl
+import java.util.LinkedHashSet
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.Project as NBProject
+import com.intellij.openapi.project.Project
+
+object NetBeansAnalyzerFacadeForJVM {
+
+ fun analyzeFilesWithJavaIntegration(
+ kotlinProject: NBProject,
+ project : Project,
+ filesToAnalyze: Collection<KtFile>): AnalysisResultWithProvider {
+ val filesSet = filesToAnalyze.toSet()
+
+ val allFiles = LinkedHashSet<KtFile>(filesSet)
+ val addedFiles = filesSet.mapNotNullTo(hashSetOf()) { getPath(it) }
+ ProjectUtils.getSourceFilesWithDependencies(kotlinProject).filterNotTo(allFiles) {
+ getPath(it) in addedFiles
+ }
+
+ val environment = KotlinEnvironment.getEnvironment(kotlinProject)
+
+ val moduleContext = createModuleContext(project,
+ environment.configuration,
+ true)
+ val storageManager = moduleContext.storageManager
+ val module = moduleContext.module
+
+ val providerFactory = FileBasedDeclarationProviderFactory(storageManager, allFiles)
+ val trace = CliLightClassGenerationSupport.CliBindingTrace()
+
+ val sourceScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, filesToAnalyze)
+ val moduleClassResolver = SourceOrBinaryModuleClassResolver(sourceScope)
+
+ val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
+ val optionalBuiltInsModule = JvmBuiltIns(storageManager).apply { initialize(module, true) }.builtInsModule
+
+ val dependencyModule = run {
+ val dependenciesContext = ContextForNewModule(
+ moduleContext, Name.special("<dependencies of ${environment.configuration.getNotNull<String>(CommonConfigurationKeys.MODULE_NAME)}>"),
+ module.builtIns, null
+ )
+
+ val dependencyScope = GlobalSearchScope.notScope(sourceScope)
+ val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
+ moduleContext,
+ trace,
+ providerFactory,
+ dependencyScope,
+ LookupTracker.DO_NOTHING,
+ KotlinPackagePartProvider(kotlinProject),
+ languageVersionSettings,
+ moduleClassResolver,
+ kotlinProject)
+
+ moduleClassResolver.compiledCodeResolver = dependenciesContainer.get()
+
+ dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule))
+ dependenciesContext.initializeModuleContents(CompositePackageFragmentProvider(listOf(
+ moduleClassResolver.compiledCodeResolver.packageFragmentProvider,
+ dependenciesContainer.get<JvmBuiltInsPackageFragmentProvider>()
+ )))
+
+ dependenciesContext.module
+ }
+
+ val container = createContainerForTopDownAnalyzerForJvm(
+ moduleContext,
+ trace,
+ providerFactory,
+ sourceScope,
+ LookupTracker.DO_NOTHING,
+ KotlinPackagePartProvider(kotlinProject),
+ languageVersionSettings,
+ moduleClassResolver,
+ kotlinProject).apply {
+ initJvmBuiltInsForTopDownAnalysis(module, languageVersionSettings)
+ }
+
+ moduleClassResolver.sourceCodeResolver = container.get()
+
+ val additionalProviders = arrayListOf<PackageFragmentProvider>()
+ additionalProviders.add(container.get<JavaDescriptorResolver>().packageFragmentProvider)
+
+ PackageFragmentProviderExtension.getInstances(project).mapNotNullTo(additionalProviders) { extension ->
+ extension.getPackageFragmentProvider(project, module, storageManager, trace, null)
+ }
+
+ module.setDependencies(ModuleDependenciesImpl(
+ listOfNotNull(module, dependencyModule, optionalBuiltInsModule),
+ setOf(dependencyModule)
+ ))
+ module.initialize(CompositePackageFragmentProvider(
+ listOf(container.get<KotlinCodeAnalyzer>().packageFragmentProvider) + additionalProviders
+ ))
+
+ try {
+ container.get<LazyTopDownAnalyzer>().analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, filesSet)
+ } catch (e: KotlinFrontEndException) {}
+
+ return AnalysisResultWithProvider(
+ AnalysisResult.success(trace.bindingContext, module),
+ container
+ )
+ }
+
+ private fun getPath(jetFile: KtFile): String? = jetFile.virtualFile?.path
+
+ private fun createModuleContext(project: Project,
+ configuration: CompilerConfiguration,
+ createBuiltInsFromModule: Boolean): MutableModuleContext {
+ val projectContext = ProjectContext(project)
+ val builtIns = JvmBuiltIns(projectContext.storageManager, !createBuiltInsFromModule)
+
+ return ContextForNewModule(
+ projectContext, Name.special("<${configuration.getNotNull<String>(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, null
+ ).apply {
+ if (createBuiltInsFromModule) {
+ builtIns.builtInsModule = module
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/NetBeansDescriptorUtils.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/NetBeansDescriptorUtils.java
new file mode 100644
index 0000000..929e46b
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/NetBeansDescriptorUtils.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind;
+import org.jetbrains.kotlin.descriptors.ClassDescriptor;
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource;
+import org.jetbrains.kotlin.descriptors.SourceElement;
+
+import com.google.common.collect.Lists;
+import org.netbeans.api.project.Project;
+
+// Note: copied with some changes from DescriptorToSourceUtils
+public class NetBeansDescriptorUtils {
+ // NOTE this is also used by KDoc
+ @Nullable
+ public static SourceElement descriptorToDeclaration(@NotNull DeclarationDescriptor descriptor) {
+ if (descriptor instanceof CallableMemberDescriptor) {
+ return callableDescriptorToDeclaration((CallableMemberDescriptor) descriptor);
+ } else if (descriptor instanceof ClassDescriptor) {
+ return classDescriptorToDeclaration((ClassDescriptor) descriptor);
+ } else {
+ return doGetDescriptorToDeclaration(descriptor);
+ }
+ }
+
+ @NotNull
+ public static List<SourceElement> descriptorToDeclarations(@NotNull DeclarationDescriptor descriptor,
+ @NotNull Project project) {
+ if (KotlinBuiltIns.isBuiltIn(descriptor)) {
+
+ Collection<DeclarationDescriptor> effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(descriptor);
+
+ HashSet<SourceElement> result = new HashSet<>();
+ BuiltInsReferenceResolver resolver = BuiltInsReferenceResolver.getInstance(project);
+ for (DeclarationDescriptor effectiveReferenced: effectiveReferencedDescriptors) {
+ DeclarationDescriptor resultDescriptor = resolver.findCurrentDescriptor(effectiveReferenced);
+ if (resultDescriptor != null && resultDescriptor instanceof DeclarationDescriptorWithSource) {
+ SourceElement element = ((DeclarationDescriptorWithSource)resultDescriptor).getSource();
+ if (!element.equals(SourceElement.NO_SOURCE)) {
+ result.add(element);
+ }
+ }
+ }
+ return new ArrayList<>(result);
+ }
+ //TODO: this returns a source element for containing element with existing .class file. This logic should be moved to a caller.
+ if (DeserializedDescriptorUtilsKt.isDeserialized(descriptor)) {
+ DeclarationDescriptor containing = DeserializedDescriptorUtilsKt.getContainingClassOrPackage(descriptor);
+ if (containing != null) {
+ return Lists.newArrayList(descriptorToDeclaration(containing));
+ }
+ }
+ if (descriptor instanceof CallableMemberDescriptor) {
+ return callableDescriptorToDeclarations((CallableMemberDescriptor) descriptor);
+ } else {
+ SourceElement sourceElement = descriptorToDeclaration(descriptor);
+ if (sourceElement != null) {
+ return Lists.newArrayList(sourceElement);
+ } else {
+ return Lists.newArrayList();
+ }
+}
+ }
+
+ @Nullable
+ public static SourceElement callableDescriptorToDeclaration(@NotNull CallableMemberDescriptor callable) {
+ if (callable.getKind() == Kind.DECLARATION || callable.getKind() == Kind.SYNTHESIZED) {
+ return doGetDescriptorToDeclaration(callable);
+ }
+ //TODO: should not use this method for fake_override and delegation
+ Collection<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
+ if (overriddenDescriptors.size() == 1) {
+ return callableDescriptorToDeclaration(overriddenDescriptors.iterator().next());
+ }
+ return null;
+ }
+
+ @NotNull
+ public static List<SourceElement> callableDescriptorToDeclarations(@NotNull CallableMemberDescriptor callable) {
+ if (callable.getKind() == Kind.DECLARATION || callable.getKind() == Kind.SYNTHESIZED) {
+ SourceElement sourceElement = doGetDescriptorToDeclaration(callable);
+ return sourceElement != null ? Lists.newArrayList(sourceElement) : Lists.<SourceElement>newArrayList();
+ }
+
+ List<SourceElement> r = Lists.newArrayList();
+ Collection<? extends CallableMemberDescriptor> overriddenDescriptors = callable.getOverriddenDescriptors();
+ for (CallableMemberDescriptor overridden : overriddenDescriptors) {
+ r.addAll(callableDescriptorToDeclarations(overridden));
+ }
+ return r;
+ }
+
+ @Nullable
+ public static SourceElement classDescriptorToDeclaration(@NotNull ClassDescriptor clazz) {
+ return doGetDescriptorToDeclaration(clazz);
+ }
+
+ @Nullable
+ private static SourceElement doGetDescriptorToDeclaration(@NotNull DeclarationDescriptor descriptor) {
+ DeclarationDescriptor original = descriptor.getOriginal();
+ if (!(original instanceof DeclarationDescriptorWithSource)) {
+ return null;
+ }
+ return ((DeclarationDescriptorWithSource) original).getSource();
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/injection.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/injection.kt
new file mode 100644
index 0000000..fdb8308
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/injection.kt
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.builtins.JvmBuiltInsPackageFragmentProvider
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.container.ComponentProvider
+import org.jetbrains.kotlin.container.StorageComponentContainer
+import org.jetbrains.kotlin.container.registerSingleton
+import org.jetbrains.kotlin.container.useInstance
+import org.jetbrains.kotlin.context.LazyResolveToken
+import org.jetbrains.kotlin.context.ModuleContext
+import org.jetbrains.kotlin.descriptors.PackagePartProvider
+import org.jetbrains.kotlin.frontend.di.configureModule
+import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer
+import org.jetbrains.kotlin.load.java.components.SignaturePropagatorImpl
+import org.jetbrains.kotlin.load.java.components.TraceBasedErrorReporter
+import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
+import org.jetbrains.kotlin.load.java.sam.SamConversionResolverImpl
+import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava
+import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinderFactory
+import org.jetbrains.kotlin.platform.JvmBuiltIns
+import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
+import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
+import org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
+import org.jetbrains.kotlin.resolve.lang.java.NetBeansJavaClassFinder
+import org.jetbrains.kotlin.resolve.lang.java.resolver.NetBeansTraceBasedJavaResolverCache
+import org.jetbrains.kotlin.resolve.lang.java.resolver.NetBeansExternalAnnotationResolver
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaPropertyInitializerEvaluator
+import org.jetbrains.kotlin.resolve.lang.java.resolver.NetBeansJavaSourceElementFactory
+import org.netbeans.api.project.Project as NBProject
+
+fun StorageComponentContainer.configureJavaTopDownAnalysis(
+ moduleContentScope: GlobalSearchScope,
+ project: Project,
+ lookupTracker: LookupTracker,
+ languageFeatureSettings: LanguageVersionSettings) {
+ useInstance(moduleContentScope)
+ useInstance(lookupTracker)
+
+ useImpl<ResolveSession>()
+
+ useImpl<LazyTopDownAnalyzer>()
+ useImpl<JavaDescriptorResolver>()
+ useImpl<DeserializationComponentsForJava>()
+
+ useInstance(JvmVirtualFileFinderFactory.SERVICE.getInstance(project).create(moduleContentScope))
+
+ useImpl<FileScopeProviderImpl>()
+
+ useImpl<NetBeansJavaClassFinder>()
+ useImpl<SignaturePropagatorImpl>()
+ useImpl<NetBeansTraceBasedJavaResolverCache>()
+ useImpl<TraceBasedErrorReporter>()
+ useImpl<NetBeansExternalAnnotationResolver>()
+ useImpl<NetBeansJavaPropertyInitializerEvaluator>()
+ useImpl<SamConversionResolverImpl>()
+ useImpl<NetBeansJavaSourceElementFactory>()
+ useInstance(InternalFlexibleTypeTransformer)
+
+ useInstance(languageFeatureSettings)
+ useImpl<CompilerDeserializationConfiguration>()
+}
+
+private fun createContainerForLazyResolveWithJava(
+ moduleContext: ModuleContext,
+ bindingTrace: BindingTrace,
+ declarationProviderFactory: DeclarationProviderFactory,
+ moduleContentScope: GlobalSearchScope,
+ moduleClassResolver: ModuleClassResolver,
+ targetEnvironment: TargetEnvironment,
+ lookupTracker: LookupTracker,
+ packagePartProvider: PackagePartProvider,
+ languageVersionSettings: LanguageVersionSettings,
+ project: NBProject,
+ useBuiltInsProvider: Boolean,
+ useLazyResolve: Boolean
+): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatform) {
+ configureModule(moduleContext, JvmPlatform, bindingTrace)
+ configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker, languageVersionSettings)
+
+ useInstance(packagePartProvider)
+ useInstance(moduleClassResolver)
+ useInstance(declarationProviderFactory)
+ useInstance(project)
+
+ if (useBuiltInsProvider) {
+ useInstance((moduleContext.module.builtIns as JvmBuiltIns).settings)
+ useImpl<JvmBuiltInsPackageFragmentProvider>()
+ }
+
+ targetEnvironment.configure(this)
+
+ if (useLazyResolve) {
+ useImpl<LazyResolveToken>()
+ }
+}.apply {
+ get<NetBeansJavaClassFinder>().initialize(bindingTrace, get())
+}
+
+fun createContainerForTopDownAnalyzerForJvm(
+ moduleContext: ModuleContext,
+ bindingTrace: BindingTrace,
+ declarationProviderFactory: DeclarationProviderFactory,
+ moduleContentScope: GlobalSearchScope,
+ lookupTracker: LookupTracker,
+ packagePartProvider: PackagePartProvider,
+ languageVersionSettings: LanguageVersionSettings,
+ moduleClassResolver: ModuleClassResolver,
+ project: NBProject
+) = createContainerForLazyResolveWithJava(
+ moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver,
+ CompilerEnvironment, lookupTracker, packagePartProvider, languageVersionSettings,
+ project, useBuiltInsProvider = true, useLazyResolve = false)
+
+// Copy functions from Dsl.kt as they were shrinked by proguard
+inline fun <reified T : Any> StorageComponentContainer.useImpl() {
+ registerSingleton(T::class.java)
+}
+
+inline fun <reified T : Any> ComponentProvider.get(): T = getService(T::class.java)
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/ElemHandle.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/ElemHandle.java
new file mode 100644
index 0000000..09ebac1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/ElemHandle.java
@@ -0,0 +1,158 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.resolve.lang.java;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.java.source.TypeMirrorHandle;
+import org.netbeans.api.project.Project;
+
+public class ElemHandle<T extends Element> {
+
+ private ElementKind kind = null;
+ private ElementHandle<T> handle = null;
+ private TypeMirrorHandle typeHandle = null;
+ private final Project project;
+
+ private ElemHandle(T element, Project project) {
+ kind = element.getKind();
+ this.project = project;
+ if (kind == ElementKind.PARAMETER || kind == ElementKind.TYPE_PARAMETER) {
+ typeHandle = TypeMirrorHandle.create(element.asType());
+ } else {
+ handle = ElementHandle.create(element);
+ }
+ }
+
+ private ElemHandle(ElementHandle<T> handle, Project project) {
+ this.handle = handle;
+ this.project = project;
+ kind = handle.getKind();
+ }
+
+ public ElementHandle<T> getElementHandle() {
+ return handle;
+ }
+
+ public TypeMirrorHandle getTypeMirrorHandle() {
+ return typeHandle;
+ }
+
+ private Element resolveTypeMirror(CompilationInfo compilationInfo) {
+ TypeMirror type = typeHandle.resolve(compilationInfo);
+ if (type == null) {
+ return null;
+ }
+
+ return ((TypeVariable) type).asElement();
+ }
+
+ public Element resolve (final CompilationInfo compilationInfo) {
+ if (handle != null) {
+ return handle.resolve(compilationInfo);
+ } else
+ return resolveTypeMirror(compilationInfo);
+ }
+
+ public String getBinaryName() {
+ if (handle != null) {
+ return handle.getBinaryName();
+ } else return null;
+ }
+
+ public String getQualifiedName() {
+ if (handle != null) {
+ return handle.getQualifiedName();
+ } else return null;
+ }
+
+ public ElementKind getKind() {
+ return kind;
+ }
+
+ public static <T extends Element> ElemHandle<T> create(final T element, Project project) {
+ return new ElemHandle(element, project);
+ }
+
+ public static <T extends Element> ElemHandle<T> create(final ElementHandle<T> element, Project project) {
+ return new ElemHandle(element, project);
+ }
+
+ public static ElemHandle<PackageElement> createPackageElementHandle (
+ final String packageName, Project project) {
+ ElementHandle elemHandle = ElementHandle.createPackageElementHandle(packageName);
+ return new ElemHandle(elemHandle, project);
+ }
+
+ public static ElemHandle<TypeElement> createTypeElementHandle(
+ final ElementKind kind, final String binaryName, Project project) {
+ ElementHandle elemHandle = ElementHandle.createTypeElementHandle(kind, binaryName);
+ return new ElemHandle(elemHandle, project);
+ }
+
+ public static ElemHandle<TypeElement> from(
+ TypeMirrorHandle typeMirrorHandle, Project project) {
+ ElementHandle elemHandle = ElementHandle.from(typeMirrorHandle);
+ return new ElemHandle(elemHandle, project);
+ }
+
+ @Override
+ public boolean equals (Object other) {
+ if (other instanceof ElemHandle) {
+ if (handle != null) {
+ return handle.equals(((ElemHandle) other).handle);
+ } else {
+ if (kind == ElementKind.TYPE_PARAMETER) {
+ return NbParameterUtilsKt.isEqual(typeHandle, ((ElemHandle)other).typeHandle, project);
+ } else
+ return NbElementUtilsKt.isEqual(typeHandle,
+ ((ElemHandle)other).typeHandle, project);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode () {
+ if (handle != null) {
+ return handle.hashCode();
+ } else {
+ if (kind == ElementKind.TYPE_PARAMETER) {
+ return NbParameterUtilsKt.getHashCode(typeHandle, project);
+ } else
+ return NbElementUtilsKt.getHashCode(typeHandle, project);
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (handle != null) {
+ return handle.toString();
+ } else {
+ return NbTypeUtilsKt.getName(typeHandle, project);
+ }
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/NetBeansJavaClassFinder.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/NetBeansJavaClassFinder.kt
new file mode 100644
index 0000000..e0e2b5f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/NetBeansJavaClassFinder.kt
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.annotation.PostConstruct
+import javax.inject.Inject
+import org.jetbrains.kotlin.load.java.JavaClassFinder
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaPackage
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClass
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaPackage
+import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.netbeans.api.project.Project
+
+class NetBeansJavaClassFinder : JavaClassFinder {
+
+ private lateinit var project: Project
+
+ @Inject fun setProjectScope(project: Project) {
+ this.project = project
+ }
+
+ @PostConstruct fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) {
+ val ideaProject = KotlinEnvironment.getEnvironment(project).project
+ CodeAnalyzerInitializer.Companion.getInstance(ideaProject).initialize(trace, codeAnalyzer.moduleDescriptor, codeAnalyzer)
+ }
+
+
+ override fun findClass(classId: ClassId): JavaClass? {
+ val element = project.findType(classId.asSingleFqName().asString()) ?: return null
+
+ return NetBeansJavaClass(element, project)
+ }
+
+ override fun findPackage(fqName: FqName): JavaPackage? {
+ val pack = project.findPackage(fqName.asString()) ?: return null
+
+ return NetBeansJavaPackage(pack, project)
+ }
+
+ override fun knownClassNamesInPackage(packageFqName: FqName) = knownClassNamesInPackage(packageFqName.asString(), project)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/annotationSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/annotationSearchers.kt
new file mode 100644
index 0000000..0db3966
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/annotationSearchers.kt
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.AnnotationMirror
+import javax.lang.model.element.AnnotationValue
+import javax.lang.model.element.VariableElement
+import javax.lang.model.type.TypeMirror
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaArrayAnnotationArgument
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaAnnotation
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaAnnotationAsAnnotationArgument
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaArrayAnnotationArgument
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClassObjectAnnotationArgument
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaLiteralAnnotationArgument
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaReferenceAnnotationArgument
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+private fun getMirrorArguments(mirror: AnnotationMirror,
+ info: CompilationController, project: Project) =
+ mirror.elementValues.map{create(it.value.value,
+ Name.identifier(it.key.simpleName.toString()), info, project) }
+
+
+private fun create(value: Any, name: Name, info: CompilationController, project: Project): JavaAnnotationArgument =
+ when(value) {
+ is AnnotationMirror -> {
+ val typeHandle = TypeMirrorHandle.create(value.annotationType)
+ NetBeansJavaAnnotationAsAnnotationArgument(project, name, typeHandle,
+ getMirrorArguments(value, info, project))
+ }
+ is VariableElement -> NetBeansJavaReferenceAnnotationArgument(ElemHandle.create(value, project), project)
+ is TypeMirror -> NetBeansJavaClassObjectAnnotationArgument(value, name, project)
+ is Collection<*> -> getArrayAnnotationArgument(value, name, info, project)
+ is AnnotationValue -> create(value.value, name, info, project)
+ else -> NetBeansJavaLiteralAnnotationArgument(value, name)
+ }
+
+private fun getArrayAnnotationArgument(values: Collection<*>, name: Name,
+ info: CompilationController,
+ project: Project): JavaArrayAnnotationArgument {
+ val args = arrayListOf<JavaAnnotationArgument>()
+ for (value in values) {
+ if (value is Collection<*>) {
+ args.add(getArrayAnnotationArgument(value, name, info, project))
+ } else args.add(create(value!!, name, info, project))
+ }
+ return NetBeansJavaArrayAnnotationArgument(args, name)
+}
+
+class AnnotationsSearcher(val handle: ElemHandle<*>, val project: Project) : Task<CompilationController> {
+ val annotations = arrayListOf<JavaAnnotation>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ for (mirror in element.annotationMirrors) {
+ val mirrorHandle = TypeMirrorHandle.create(mirror.annotationType)
+ annotations.add(NetBeansJavaAnnotation(project, mirrorHandle,
+ getMirrorArguments(mirror, info, project)))
+ }
+ }
+}
+
+class AnnotationsForTypeMirrorHandleSearcher(val handle: TypeMirrorHandle<*>,
+ val project: Project) : Task<CompilationController> {
+ val annotations = arrayListOf<JavaAnnotation>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ for (mirror in element.annotationMirrors) {
+ val mirrorHandle = TypeMirrorHandle.create(mirror.annotationType)
+ annotations.add(NetBeansJavaAnnotation(project, mirrorHandle,
+ getMirrorArguments(mirror, info, project)))
+ }
+ }
+}
+
+class AnnotationSearcher(val handle: ElemHandle<*>, val project: Project,
+ val fqName: FqName) : Task<CompilationController> {
+ var annotation: JavaAnnotation? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ for (mirror in element.annotationMirrors) {
+ val annotationFqName = mirror.annotationType.toString()
+ if (fqName.asString() == annotationFqName) {
+ val mirrorHandle = TypeMirrorHandle.create(mirror.annotationType)
+ annotation = NetBeansJavaAnnotation(project, mirrorHandle,
+ getMirrorArguments(mirror, info, project))
+ }
+ }
+ }
+}
+
+class AnnotationForTypeMirrorHandleSearcher(val handle: TypeMirrorHandle<*>, val project: Project,
+ val fqName: FqName) : Task<CompilationController> {
+ var annotation: JavaAnnotation? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ for (mirror in element.annotationMirrors) {
+ val annotationFqName = mirror.annotationType.toString()
+ if (fqName.asString() == annotationFqName) {
+ val mirrorHandle = TypeMirrorHandle.create(mirror.annotationType)
+ annotation = NetBeansJavaAnnotation(project, mirrorHandle,
+ getMirrorArguments(mirror, info, project))
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/classSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/classSearchers.kt
new file mode 100644
index 0000000..7d55457
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/classSearchers.kt
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.ElementKind
+import javax.lang.model.element.ExecutableElement
+import javax.lang.model.element.TypeElement
+import javax.lang.model.element.VariableElement
+import javax.lang.model.type.NoType
+import javax.lang.model.type.TypeKind
+import javax.lang.model.type.TypeMirror
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
+import org.jetbrains.kotlin.load.java.structure.JavaConstructor
+import org.jetbrains.kotlin.load.java.structure.JavaField
+import org.jetbrains.kotlin.load.java.structure.JavaMethod
+import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.name.SpecialNames
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClass
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClassifierType
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaConstructor
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaField
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaMethod
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaTypeParameter
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+import com.intellij.psi.CommonClassNames
+
+class NameSearcher(val handle: ElemHandle<TypeElement>) : Task<CompilationController> {
+ var name: Name = SpecialNames.safeIdentifier(handle.qualifiedName)
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ name = SpecialNames.safeIdentifier(element.simpleName.toString())
+ }
+}
+
+class SuperTypesSearcher(val handle: ElemHandle<TypeElement>, val project: Project) : Task<CompilationController> {
+ val superTypes = arrayListOf<JavaClassifierType>()
+
+ private fun getSuperTypesMirrors(typeBinding: TypeElement): List<TypeMirror> {
+ val superTypesList = typeBinding.interfaces.toMutableList()
+
+ val superclass = typeBinding.superclass
+ if (superclass !is NoType) superTypesList.add(superclass)
+
+ return superTypesList
+ }
+
+ private fun getSuperTypesWithObject(typeBinding: TypeElement, info: CompilationController): Array<TypeMirror> {
+ val allSuperTypes = getSuperTypesMirrors(typeBinding).toMutableList()
+ val hasObject = !allSuperTypes.none{ it.toString() == CommonClassNames.JAVA_LANG_OBJECT }
+
+ if (!hasObject && typeBinding.toString() != CommonClassNames.JAVA_LANG_OBJECT) {
+ allSuperTypes.add(info.elements.getTypeElement(CommonClassNames.JAVA_LANG_OBJECT).asType())
+ }
+
+ return allSuperTypes.toTypedArray()
+ }
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ getSuperTypesWithObject(element as TypeElement, info)
+ .forEach{ superTypes.add(
+ NetBeansJavaClassifierType(TypeMirrorHandle.create(it), project)) }
+ }
+}
+
+class InnerClassesSearcher(val handle: ElemHandle<TypeElement>,
+ val project: Project) : Task<CompilationController> {
+ val innerClasses = arrayListOf<JavaClass>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ val filteredMembers = element.enclosedElements
+ .filterIsInstance(TypeElement::class.java)
+ .map{ NetBeansJavaClass(ElemHandle.create(it, project), project) }
+ innerClasses.addAll(filteredMembers)
+ }
+}
+
+class OuterClassSearcher(val handle: ElemHandle<TypeElement>,
+ val project: Project) : Task<CompilationController> {
+ var outerClass: JavaClass? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ val outer = element.enclosingElement ?: return
+ if (outer.asType().kind != TypeKind.DECLARED) return
+
+ outerClass = NetBeansJavaClass(ElemHandle.create(outer as TypeElement, project), project)
+ }
+}
+
+class MethodsSearcher(val handle: ElemHandle<TypeElement>,
+ val project: Project, val containingClass: JavaClass) : Task<CompilationController> {
+ val methods = arrayListOf<JavaMethod>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ val filteredMembers = element.enclosedElements
+ .filter { it.kind == ElementKind.METHOD }
+ .map { NetBeansJavaMethod(ElemHandle.create(it as ExecutableElement, project), containingClass, project) }
+ methods.addAll(filteredMembers)
+ }
+}
+
+class MethodHandlesSearcher(val handle: ElementHandle<TypeElement>) : Task<CompilationController> {
+ val methods = arrayListOf<ElementHandle<ExecutableElement>>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ val filteredMembers = element.enclosedElements
+ .filter{ it.kind == ElementKind.METHOD }
+ .map { ElementHandle.create(it as ExecutableElement) }
+
+ methods.addAll(filteredMembers)
+ }
+}
+
+class ConstructorsSearcher(val handle: ElemHandle<TypeElement>,
+ val project: Project, val containingClass: JavaClass) : Task<CompilationController> {
+ val constructors = arrayListOf<JavaConstructor>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ val filteredMembers = element.enclosedElements
+ .filter { it.kind == ElementKind.CONSTRUCTOR }
+ .map { NetBeansJavaConstructor(ElemHandle.create(it as ExecutableElement, project), containingClass, project) }
+ constructors.addAll(filteredMembers)
+ }
+}
+
+class FieldsSearcher(val handle: ElemHandle<TypeElement>,
+ val project: Project, val containingClass: JavaClass) : Task<CompilationController> {
+ val fields = arrayListOf<JavaField>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ val filteredMembers = element.enclosedElements
+ .filter { it.kind.isField && Name.isValidIdentifier(it.simpleName.toString()) }
+ .map { NetBeansJavaField(ElemHandle.create(it as VariableElement, project), containingClass, project) }
+ fields.addAll(filteredMembers)
+ }
+}
+
+class TypeParametersSearcher(val handle: ElemHandle<TypeElement>,
+ val project: Project) : Task<CompilationController> {
+ val typeParameters = arrayListOf<JavaTypeParameter>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+ val element = handle.resolve(info) ?: return
+
+ (element as TypeElement).typeParameters
+ .forEach{ typeParameters.add(NetBeansJavaTypeParameter(ElemHandle.create(it, project), project)) }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/executableSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/executableSearchers.kt
new file mode 100644
index 0000000..74b23cb
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/executableSearchers.kt
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.ExecutableElement
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
+import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaType
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaTypeParameter
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaValueParameter
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+class ReturnTypeSearcher(val handle: ElemHandle<ExecutableElement>,
+ val project: Project) : Task<CompilationController> {
+
+ lateinit var returnType: JavaType
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ val typeHandle = TypeMirrorHandle.create((elem as ExecutableElement).returnType)
+ returnType = NetBeansJavaType.create(typeHandle, project)
+ }
+}
+
+class HasAnnotationParameterDefaultValueSearcher(val handle: ElemHandle<ExecutableElement>) : Task<CompilationController> {
+
+ var hasAnnotationParameterDefaultValue = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ hasAnnotationParameterDefaultValue = (elem as ExecutableElement).defaultValue != null
+ }
+}
+
+class ExecutableTypeParametersSearcher(val handle: ElemHandle<ExecutableElement>,
+ val project: Project) : Task<CompilationController> {
+
+ val typeParameters = arrayListOf<JavaTypeParameter>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ val typeParams = (elem as ExecutableElement).typeParameters
+ .map { NetBeansJavaTypeParameter(ElemHandle.create(it, project), project) }
+ typeParameters.addAll(typeParams)
+ }
+}
+
+class ValueParametersSearcher(val handle: ElemHandle<ExecutableElement>,
+ val project: Project) : Task<CompilationController> {
+
+ val valueParameters = arrayListOf<JavaValueParameter>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ val valueParams = (elem as ExecutableElement).parameters
+ val parameterTypesCount = valueParams.size
+
+ valueParams.forEachIndexed { index, it ->
+ val isLastParameter = index == parameterTypesCount - 1
+ val parameterName = it.simpleName.toString()
+ val elemHandle = ElemHandle.create(it, project)
+ val valueParameter = NetBeansJavaValueParameter(elemHandle, project, parameterName,
+ if (isLastParameter) elem.isVarArgs else false)
+ valueParameters.add(valueParameter)
+ }
+ }
+}
+
+class ElementHandleValueParametersSearcher(val handle: ElementHandle<ExecutableElement>,
+ val project: Project) : Task<CompilationController> {
+
+ val valueParameters = arrayListOf<JavaValueParameter>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ val valueParams = elem.parameters
+ val parameterTypesCount = valueParams.size
+
+ valueParams.forEachIndexed { index, it ->
+ val isLastParameter = index == parameterTypesCount - 1
+ val parameterName = it.simpleName.toString()
+ val elemHandle = ElemHandle.create(it, project)
+ val valueParameter = NetBeansJavaValueParameter(elemHandle, project, parameterName,
+ if (isLastParameter) elem.isVarArgs else false)
+ valueParameters.add(valueParameter)
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/memberSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/memberSearchers.kt
new file mode 100644
index 0000000..088a843
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/memberSearchers.kt
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.Modifier
+import javax.lang.model.element.TypeElement
+import javax.lang.model.element.VariableElement
+import org.jetbrains.kotlin.descriptors.Visibilities
+import org.jetbrains.kotlin.load.java.JavaVisibilities
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaType
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+class IsAbstractSearcher(val handle: ElemHandle<*>) : Task<CompilationController> {
+
+ var isAbstract = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ isAbstract = elem.modifiers.contains(Modifier.ABSTRACT)
+ }
+}
+
+class IsStaticSearcher(val handle: ElemHandle<*>) : Task<CompilationController> {
+
+ var isStatic = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ isStatic = elem.modifiers.contains(Modifier.STATIC)
+ }
+}
+
+class IsFinalSearcher(val handle: ElemHandle<*>) : Task<CompilationController> {
+
+ var isFinal = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ isFinal = elem.modifiers.contains(Modifier.FINAL)
+ }
+}
+
+class MemberNameSearcher(val handle: ElemHandle<*>) : Task<CompilationController> {
+
+ lateinit var name: Name
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ name = Name.identifier(elem.simpleName.toString())
+ }
+}
+
+class MemberElementHandleNameSearcher(val handle: ElementHandle<*>) : Task<CompilationController> {
+
+ lateinit var name: Name
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ name = Name.identifier(elem.simpleName.toString())
+ }
+}
+
+class ElementHandleNameSearcher(val handle: ElementHandle<*>) : Task<CompilationController> {
+
+ lateinit var name: Name
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ name = Name.identifier(elem.simpleName.toString())
+ }
+}
+
+class VisibilitySearcher(val handle: ElemHandle<*>) : Task<CompilationController> {
+
+ var visibility = JavaVisibilities.PACKAGE_VISIBILITY
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ val modifiers = elem.modifiers
+ visibility = when {
+ modifiers.contains(Modifier.PUBLIC) -> Visibilities.PUBLIC
+ modifiers.contains(Modifier.PRIVATE) -> Visibilities.PRIVATE
+ modifiers.contains(Modifier.PROTECTED) -> {
+ if (modifiers.contains(Modifier.STATIC)) {
+ JavaVisibilities.PROTECTED_STATIC_VISIBILITY
+ } else {
+ JavaVisibilities.PROTECTED_AND_PACKAGE
+ }
+ }
+ else -> JavaVisibilities.PACKAGE_VISIBILITY
+ }
+ }
+}
+
+class FieldTypeSearcher(val handle: ElemHandle<*>,
+ val project: Project) : Task<CompilationController> {
+
+ lateinit var type: JavaType
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ val mirror = (elem as VariableElement).asType()
+ type = NetBeansJavaType.create(TypeMirrorHandle.create(mirror), project)
+ }
+}
+
+class FieldContainingClassSearcher(val handle: ElemHandle<*>,
+ val project: Project) : Task<CompilationController> {
+
+ lateinit var containingClass: ElemHandle<TypeElement>
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ containingClass = ElemHandle.create(elem.enclosingElement as TypeElement, project)
+ }
+}
+
+class ElementHandleFieldContainingClassSearcher(val handle: ElementHandle<*>) : Task<CompilationController> {
+
+ lateinit var containingClass: ElementHandle<*>
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info)
+ containingClass = ElementHandle.create(elem.enclosingElement)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbAnnotationUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbAnnotationUtils.kt
new file mode 100644
index 0000000..bf39c6e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbAnnotationUtils.kt
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import org.jetbrains.kotlin.name.FqName
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+fun ElemHandle<*>.getAnnotations(project: Project) =
+ AnnotationsSearcher(this, project).execute(project).annotations
+
+fun ElemHandle<*>.getAnnotation(project: Project, fqName: FqName) =
+ AnnotationSearcher(this, project, fqName).execute(project).annotation
+
+fun TypeMirrorHandle<*>.getAnnotations(project: Project) =
+ AnnotationsForTypeMirrorHandleSearcher(this, project).execute(project).annotations
+
+fun TypeMirrorHandle<*>.getAnnotation(project: Project, fqName: FqName) =
+ AnnotationForTypeMirrorHandleSearcher(this, project, fqName).execute(project).annotation
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbClassUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbClassUtils.kt
new file mode 100644
index 0000000..c60c680
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbClassUtils.kt
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.name.FqName
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.project.Project
+import javax.lang.model.element.TypeElement
+
+
+fun ElemHandle<TypeElement>.getName(project: Project) = NameSearcher(this).execute(project).name
+
+fun ElemHandle<TypeElement>.getSuperTypes(project: Project) =
+ SuperTypesSearcher(this, project).execute(project).superTypes
+
+fun ElemHandle<TypeElement>.getInnerClasses(project: Project) =
+ InnerClassesSearcher(this, project).execute(project).innerClasses
+
+fun ElemHandle<TypeElement>.getOuterClass(project: Project) =
+ OuterClassSearcher(this, project).execute(project).outerClass
+
+fun ElemHandle<TypeElement>.getMethods(project: Project, javaClass: JavaClass) =
+ MethodsSearcher(this, project, javaClass).execute(project).methods
+
+fun ElemHandle<TypeElement>.getConstructors(project: Project, javaClass: JavaClass) =
+ ConstructorsSearcher(this, project, javaClass).execute(project).constructors
+
+fun ElemHandle<TypeElement>.getFields(project: Project, javaClass: JavaClass) =
+ FieldsSearcher(this, project, javaClass).execute(project).fields
+
+fun ElemHandle<TypeElement>.getTypeParameters(project: Project) =
+ TypeParametersSearcher(this, project).execute(project).typeParameters
+
+fun ElemHandle<TypeElement>.getFqName() = FqName(this.qualifiedName)
+
+fun ElementHandle<TypeElement>.getMethodsHandles(project: Project) =
+ MethodHandlesSearcher(this).execute(project).methods
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbElementUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbElementUtils.kt
new file mode 100644
index 0000000..deb2b1d
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbElementUtils.kt
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.TypeElement
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.getExtendedClassPath
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClass
+import org.netbeans.api.java.classpath.ClassPath
+import org.netbeans.api.java.source.ClassIndex
+import org.netbeans.api.java.source.ClasspathInfo
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.java.source.JavaSource
+import org.netbeans.api.java.source.SourceUtils
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.java.source.ui.ElementOpen
+import org.netbeans.api.project.Project
+import org.openide.filesystems.FileObject
+import javax.lang.model.type.DeclaredType
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
+import javax.lang.model.element.ElementKind
+import javax.lang.model.element.ExecutableElement
+
+object JavaEnvironment {
+ val JAVA_SOURCE = hashMapOf<Project, JavaSource>()
+
+ private fun getClasspathInfo(project: Project): ClasspathInfo {
+ val extendedProvider = project.getExtendedClassPath() ?:
+ return ClasspathInfo.create(ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY)
+
+ val boot = extendedProvider.getProjectSourcesClassPath(ClassPath.BOOT)
+ val src = extendedProvider.getProjectSourcesClassPath(ClassPath.SOURCE)
+ val compile = extendedProvider.getProjectSourcesClassPath(ClassPath.COMPILE)
+
+ return ClasspathInfo.create(boot, compile, src)
+ }
+
+ fun updateClasspathInfo(project: Project) {
+ JAVA_SOURCE.put(project, JavaSource.create(getClasspathInfo(project)))
+ }
+
+ fun checkJavaSource(project: Project) {
+ if (!JAVA_SOURCE.containsKey(project)) {
+ JAVA_SOURCE.put(project, JavaSource.create(getClasspathInfo(project)))
+ }
+ }
+
+}
+
+fun knownClassNamesInPackage(packageFqName: String, project: Project): Set<String> {
+ val classes = hashSetOf<String>()
+ JavaEnvironment.checkJavaSource(project)
+ JavaEnvironment.JAVA_SOURCE[project]?.let {
+ it.runUserActionTask({
+ it.toResolvedPhase()
+ it.elements.getPackageElement(packageFqName)
+ ?.enclosedElements
+ ?.filterIsInstance(TypeElement::class.java)
+ ?.map { it.simpleName.toString() }
+ ?.let { classes.addAll(it) }
+ }, true)
+ }
+
+ return classes
+}
+
+fun ElementHandle<*>.getFileObject(project: Project): FileObject? =
+ SourceUtils.getFile(this, JavaEnvironment.JAVA_SOURCE[project]!!.classpathInfo)
+
+fun String.getPackages(project: Project): Set<String> {
+ JavaEnvironment.checkJavaSource(project)
+ return JavaEnvironment.JAVA_SOURCE[project]!!.classpathInfo.classIndex.
+ getPackageNames(this, false, hashSetOf(ClassIndex.SearchScope.SOURCE, ClassIndex.SearchScope.DEPENDENCIES))
+}
+
+fun Project.findType(fqName: String) = TypeElementSearcher(fqName, this).execute(this).element
+
+fun Project.findTypeElementHandle(fqName: String) = TypeElementHandleSearcher(fqName, this).execute(this).element
+
+fun <T : Task<CompilationController>> T.execute(project: Project): T {
+ JavaEnvironment.checkJavaSource(project)
+ JavaEnvironment.JAVA_SOURCE[project]!!.runUserActionTask(this, true)
+
+ return this
+}
+
+fun CompilationController.toResolvedPhase(): JavaSource.Phase = this.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED)
+
+fun Project.findPackage(name: String) =
+ PackageElementSearcher(name, this).execute(this).`package`
+
+fun ElemHandle<TypeElement>.computeClassId(project: Project) =
+ ClassIdComputer(this).execute(project).classId
+
+fun ElemHandle<*>.getSimpleName(project: Project) =
+ ElementSimpleNameSearcher(this).execute(project).simpleName
+
+fun TypeMirrorHandle<*>.getHashCode(project: Project) =
+ TypeMirrorHandleHashCodeSearcher(this).execute(project).hashCode
+
+fun TypeMirrorHandle<*>.isEqual(handle: TypeMirrorHandle<*>, project: Project) =
+ TypeMirrorHandleEquals(this, handle).execute(project).equals
+
+fun Project.findFQName(name: String): List<String> {
+ JavaEnvironment.checkJavaSource(this)
+
+ return JavaEnvironment.JAVA_SOURCE[this]!!.classpathInfo.classIndex.
+ getDeclaredTypes(name, ClassIndex.NameKind.SIMPLE_NAME,
+ setOf(ClassIndex.SearchScope.SOURCE,
+ ClassIndex.SearchScope.DEPENDENCIES))
+ .map { it.qualifiedName }
+}
+
+fun Project.findTypes(prefix: String): List<ElementHandle<TypeElement>> {
+ JavaEnvironment.checkJavaSource(this)
+
+ return JavaEnvironment.JAVA_SOURCE[this]!!.classpathInfo.classIndex.
+ getDeclaredTypes(prefix, ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX,
+ setOf(ClassIndex.SearchScope.SOURCE,
+ ClassIndex.SearchScope.DEPENDENCIES)).toList()
+}
+
+fun ElementHandle<*>.openInEditor(project: Project) =
+ ElementOpen.open(JavaEnvironment.JAVA_SOURCE[project]?.classpathInfo, this)
+
+fun TypeMirrorHandle<*>.getJavaClass(project: Project) =
+ NetBeansJavaClass(ElemHandle.from(this, project), project)
+
+fun TypeMirrorHandle<DeclaredType>.computeClassId(project: Project) =
+ ElemHandle.from(this, project).computeClassId(project)
+
+fun ElemHandle<*>.isDeprecated(project: Project) =
+ IsDeprecatedSearcher(this).execute(project).isDeprecated
+
+fun searchKinds() = setOf(ClassIndex.SearchKind.FIELD_REFERENCES,
+ ClassIndex.SearchKind.IMPLEMENTORS,
+ ClassIndex.SearchKind.METHOD_REFERENCES,
+ ClassIndex.SearchKind.TYPE_REFERENCES)
+
+fun ElemHandle<*>.getJavaDoc(project: Project) =
+ JavaDocSearcher(this).execute(project).javaDoc
+
+fun ElementHandle<TypeElement>.findMember(descriptor: DeclarationDescriptor,
+ project: Project): ElementHandle<*>? {
+ var member: ElementHandle<*>? = null
+ val finder = Task<CompilationController> { info ->
+ info.toResolvedPhase()
+
+ val typeElement = this.resolve(info)
+ if (typeElement != null) {
+ val filteredMembers = if (descriptor is CallableMemberDescriptor) {
+ //TODO check signatures
+ typeElement.enclosedElements
+ .filterIsInstance(ExecutableElement::class.java)
+ .filter { it.kind == ElementKind.METHOD && it.simpleName.toString() == descriptor.name.asString() }
+ } else typeElement.enclosedElements
+ .filter { it.kind == ElementKind.FIELD && it.simpleName.toString() == descriptor.name.asString() }
+ val memberElement = filteredMembers.firstOrNull()
+ if (memberElement != null) member = ElementHandle.create(memberElement)
+ }
+
+ }
+
+ finder.execute(project)
+ return member
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbExecutableUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbExecutableUtils.kt
new file mode 100644
index 0000000..2ba8493
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbExecutableUtils.kt
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.ExecutableElement
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.project.Project
+
+fun ElemHandle<ExecutableElement>.getReturnType(project: Project) =
+ ReturnTypeSearcher(this, project).execute(project).returnType
+
+fun ElemHandle<ExecutableElement>.hasAnnotationParameterDefaultValue(project: Project) =
+ HasAnnotationParameterDefaultValueSearcher(this).execute(project).hasAnnotationParameterDefaultValue
+
+fun ElemHandle<ExecutableElement>.getTypeParameters(project: Project) =
+ ExecutableTypeParametersSearcher(this, project).execute(project).typeParameters
+
+fun ElemHandle<ExecutableElement>.getValueParameters(project: Project) =
+ ValueParametersSearcher(this, project).execute(project).valueParameters
+
+fun ElementHandle<ExecutableElement>.getElementHandleValueParameters(project: Project) =
+ ElementHandleValueParametersSearcher(this, project).execute(project).valueParameters
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbMemberUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbMemberUtils.kt
new file mode 100644
index 0000000..f1fe18f
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbMemberUtils.kt
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.project.Project
+import javax.lang.model.element.VariableElement
+
+fun ElemHandle<*>.isAbstract(project: Project) =
+ IsAbstractSearcher(this).execute(project).isAbstract
+
+fun ElemHandle<*>.isStatic(project: Project) =
+ IsStaticSearcher(this).execute(project).isStatic
+
+fun ElemHandle<*>.isFinal(project: Project) =
+ IsFinalSearcher(this).execute(project).isFinal
+
+fun ElemHandle<*>.getName(project: Project) =
+ MemberNameSearcher(this).execute(project).name
+
+fun ElementHandle<*>.getName(project: Project) =
+ MemberElementHandleNameSearcher(this).execute(project).name
+
+fun ElemHandle<*>.getVisibility(project: Project) =
+ VisibilitySearcher(this).execute(project).visibility
+
+fun ElemHandle<VariableElement>.getFieldType(project: Project) =
+ FieldTypeSearcher(this, project).execute(project).type
+
+fun ElemHandle<VariableElement>.getContainingClass(project: Project) =
+ FieldContainingClassSearcher(this, project).execute(project).containingClass
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbPackageUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbPackageUtils.kt
new file mode 100644
index 0000000..5e61220
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbPackageUtils.kt
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.PackageElement
+import org.jetbrains.kotlin.load.java.structure.JavaPackage
+import org.jetbrains.kotlin.name.Name
+import org.netbeans.api.project.Project
+
+fun JavaPackage.getSubPackages(project: Project) =
+ SubPackagesSearcher(project, this).execute(project).subPackages
+
+fun List<ElemHandle<PackageElement>>.getClasses(project: Project, nameFilter: (Name) -> Boolean) =
+ ClassesSearcher(this, project, nameFilter).execute(project).classes
+
+fun ElemHandle<PackageElement>.getFqName(project: Project) =
+ FqNameSearcher(this).execute(project).fqName
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbParameterUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbParameterUtils.kt
new file mode 100644
index 0000000..c69b538
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbParameterUtils.kt
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.TypeParameterElement
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+import javax.lang.model.type.TypeVariable
+
+fun ElemHandle<TypeParameterElement>.getName(project: Project) =
+ TypeParameterNameSearcher(this).execute(project).name
+
+fun TypeMirrorHandle<*>.toElemHandle(project: Project) =
+ ElemHandleSearcher(this, project).execute(project).elemHandle
+
+fun ElemHandle<TypeParameterElement>.getUpperBounds(project: Project) =
+ UpperBoundsSearcher(this, project).execute(project).upperBounds
+
+fun TypeMirrorHandle<TypeVariable>.getHashCode(project: Project) =
+ TypeParameterHashCodeSearcher(this).execute(project).hashCode
+
+fun TypeMirrorHandle<TypeVariable>.isEqual(handle: TypeMirrorHandle<*>, project: Project) =
+ Equals(this, handle).execute(project).equals
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbTypeUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbTypeUtils.kt
new file mode 100644
index 0000000..ce798c9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/nbTypeUtils.kt
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+fun TypeMirrorHandle<*>.getName(project: Project) =
+ TypeNameSearcher(this).execute(project).name
+
+fun TypeMirrorHandle<*>.getBound(project: Project) =
+ BoundSearcher(this, project).execute(project).bound
+
+fun TypeMirrorHandle<*>.isExtends(project: Project) =
+ IsExtendsSearcher(this).execute(project).isExtends
+
+fun TypeMirrorHandle<*>.getComponentType(project: Project) =
+ ComponentTypeSearcher(this, project).execute(project).componentType
+
+fun TypeMirrorHandle<*>.isRaw(project: Project) =
+ IsRawSearcher(this).execute(project).isRaw
+
+fun TypeMirrorHandle<*>.getTypeArguments(project: Project) =
+ TypeArgumentsSearcher(this, project).execute(project).typeArguments
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/packageSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/packageSearchers.kt
new file mode 100644
index 0000000..e3124e2
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/packageSearchers.kt
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.PackageElement
+import javax.lang.model.element.TypeElement
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaPackage
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClass
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaPackage
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.project.Project
+
+class SubPackagesSearcher(val project: Project,
+ private val pack: JavaPackage) : Task<CompilationController> {
+
+ val subPackages = arrayListOf<JavaPackage>()
+
+ private fun findPackageFragments(name: String, info: CompilationController): Array<PackageElement>? =
+ name.getPackages(project)
+ .mapNotNull { info.elements.getPackageElement(it) }
+ .takeIf { it.isNotEmpty() }
+ ?.toTypedArray()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val thisPackageName = pack.fqName.asString()
+ val pattern = if (thisPackageName.isEmpty()) "*" else "$thisPackageName."
+
+ val packageFragments = findPackageFragments(pattern, info)
+ val thisNestedLevel = thisPackageName.split("\\.").size
+
+ if (packageFragments != null && packageFragments.isNotEmpty()) {
+ packageFragments.forEach {
+ val subNestedLevel = it.qualifiedName.toString().split("\\.").size
+ val applicableForRootPackage = thisNestedLevel == 1 && thisNestedLevel == subNestedLevel
+ if (!it.qualifiedName.toString().isEmpty() &&
+ (applicableForRootPackage || (thisNestedLevel + 1 == subNestedLevel))) {
+ subPackages.add(NetBeansJavaPackage(ElemHandle.create(it, project), project))
+ }
+ }
+ }
+ }
+}
+
+class ClassesSearcher(private val packages: List<ElemHandle<PackageElement>>,
+ val project: Project,
+ private val nameFilter: (Name) -> Boolean) : Task<CompilationController> {
+
+ val classes = arrayListOf<JavaClass>()
+
+ private fun isOuterClass(classFile: TypeElement) = !classFile.simpleName.toString().contains("$")
+
+ private fun getClassesInPackage(javaPackage: PackageElement, nameFilter: (Name) -> Boolean): List<JavaClass> {
+ return javaPackage.enclosedElements
+ .filter {
+ isOuterClass(it as TypeElement) && Name.isValidIdentifier(it.simpleName.toString())
+ && nameFilter.invoke(Name.identifier(it.simpleName.toString()))
+ }
+ .map { NetBeansJavaClass(ElemHandle.create(it as TypeElement, project), project) }
+ }
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ packages.mapNotNull { it -> it.resolve(info) }
+ .forEach { classes.addAll(getClassesInPackage(it as PackageElement, nameFilter)) }
+ }
+}
+
+class FqNameSearcher(val handle: ElemHandle<PackageElement>) : Task<CompilationController> {
+
+ lateinit var fqName: FqName
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val pack = handle.resolve(info) ?: throw UnsupportedOperationException("Couldn''t resolve $handle")
+ fqName = FqName((pack as PackageElement).qualifiedName.toString())
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/parameterSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/parameterSearchers.kt
new file mode 100644
index 0000000..af84c18
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/parameterSearchers.kt
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.TypeParameterElement
+import javax.lang.model.type.TypeVariable
+import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.name.SpecialNames
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClassifierType
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+class TypeParameterNameSearcher(val handle: ElemHandle<*>) : Task<CompilationController> {
+
+ lateinit var name: Name
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: throw UnsupportedOperationException("Couldn't resolve '$handle")
+ name = SpecialNames.safeIdentifier(elem.simpleName.toString())
+ }
+}
+
+class TypeParameterHashCodeSearcher(val handle: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ var hashCode = handle.hashCode()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: return
+ hashCode = (type as TypeVariable).asElement().hashCode()
+ }
+}
+
+class TypeMirrorHandleHashCodeSearcher(val handle: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ var hashCode = handle.hashCode()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: return
+ hashCode = type.hashCode()
+ }
+}
+
+class ElemHandleSearcher(private val typeHandle: TypeMirrorHandle<*>,
+ val project: Project) : Task<CompilationController> {
+
+ lateinit var elemHandle: ElemHandle<TypeParameterElement>
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val mirror = typeHandle.resolve(info) as? TypeVariable ?: throw UnsupportedOperationException("Cpuldn't resolve ${typeHandle}'")
+ elemHandle = ElemHandle.create(mirror.asElement() as TypeParameterElement, project)
+ }
+}
+
+class UpperBoundsSearcher(val handle: ElemHandle<*>, val project: Project) : Task<CompilationController> {
+
+ val upperBounds = arrayListOf<JavaClassifierType>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ val type = (elem as TypeParameterElement).asType()
+ upperBounds.add(NetBeansJavaClassifierType(TypeMirrorHandle.create((type as TypeVariable).upperBound), project))
+ }
+}
+
+class Equals(val handle: TypeMirrorHandle<*>,
+ private val handle2: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ var equals = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) as? TypeVariable ?: return
+ val type2 = handle2.resolve(info) as? TypeVariable ?: return
+
+ equals = type.asElement() == type2.asElement()
+ }
+}
+
+class TypeMirrorHandleEquals(val handle: TypeMirrorHandle<*>,
+ private val handle2: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ var equals = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: return
+ val type2 = handle2.resolve(info) ?: return
+
+ equals = type == type2
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansExternalAnnotationResolver.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansExternalAnnotationResolver.kt
new file mode 100644
index 0000000..a840c3d1
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansExternalAnnotationResolver.kt
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.resolver
+
+import org.jetbrains.kotlin.load.java.components.ExternalAnnotationResolver
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner
+import org.jetbrains.kotlin.name.FqName
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 26, 2016
+*/
+
+class NetBeansExternalAnnotationResolver : ExternalAnnotationResolver {
+
+ override fun findExternalAnnotation(owner: JavaAnnotationOwner, fqName: FqName) = null
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansJavaSourceElement.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansJavaSourceElement.kt
new file mode 100644
index 0000000..5089fcb
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansJavaSourceElement.kt
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.resolver
+
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaElement
+import org.jetbrains.kotlin.descriptors.SourceFile
+import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 26, 2016
+*/
+
+class NetBeansJavaSourceElement(override val javaElement: JavaElement) : JavaSourceElement {
+
+ override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
+
+ fun getElementBinding() = (javaElement as NetBeansJavaElement<*>).elementHandle
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansJavaSourceElementFactory.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansJavaSourceElementFactory.kt
new file mode 100644
index 0000000..a46ef82
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansJavaSourceElementFactory.kt
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.resolver
+
+import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 26, 2016
+*/
+
+class NetBeansJavaSourceElementFactory : JavaSourceElementFactory {
+
+ override fun source(javaElement: JavaElement) = NetBeansJavaSourceElement(javaElement)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansTraceBasedJavaResolverCache.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansTraceBasedJavaResolverCache.kt
new file mode 100644
index 0000000..0d11b19
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/resolver/NetBeansTraceBasedJavaResolverCache.kt
@@ -0,0 +1,66 @@
+package org.jetbrains.kotlin.resolve.lang.java.resolver
+
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
+import org.jetbrains.kotlin.load.java.components.JavaResolverCache
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+import org.jetbrains.kotlin.load.java.structure.JavaField
+import org.jetbrains.kotlin.load.java.structure.JavaMethod
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.tail
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils
+import javax.inject.Inject
+
+class NetBeansTraceBasedJavaResolverCache : JavaResolverCache {
+ private lateinit var trace: BindingTrace
+ private lateinit var resolveSession: ResolveSession
+
+ @Inject
+ fun setTrace(trace: BindingTrace) {
+ this.trace = trace
+ }
+
+ @Inject
+ fun setResolveSession(resolveSession: ResolveSession) {
+ this.resolveSession = resolveSession
+ }
+
+ override fun getClassResolvedFromSource(fqName: FqName): ClassDescriptor? =
+ trace[BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, fqName.toUnsafe()] ?: findInPackageFragments(fqName)
+
+ override fun recordMethod(method: JavaMethod, descriptor: SimpleFunctionDescriptor) {
+ }
+
+ override fun recordConstructor(element: JavaElement, descriptor: ConstructorDescriptor) {
+ }
+
+ override fun recordField(field: JavaField, descriptor: PropertyDescriptor) {
+ }
+
+ override fun recordClass(javaClass: JavaClass, descriptor: ClassDescriptor) {
+ }
+
+ // Copied from org.jetbrains.kotlin.load.java.components.LazyResolveBasedCache
+ private fun findInPackageFragments(fullFqName: FqName): ClassDescriptor? {
+ var fqName = if (fullFqName.isRoot) fullFqName else fullFqName.parent()
+
+ while (true) {
+ val packageDescriptor = resolveSession.getPackageFragment(fqName) ?: break
+
+ val result = ResolveSessionUtils.findClassByRelativePath(
+ packageDescriptor.getMemberScope(), fullFqName.tail(fqName))
+ if (result != null) return result
+
+ if (fqName.isRoot) break
+ fqName = fqName.parent()
+ }
+
+ return null
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/searchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/searchers.kt
new file mode 100644
index 0000000..1ab62bb
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/searchers.kt
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import com.sun.javadoc.Doc
+import javax.lang.model.element.ElementKind
+import javax.lang.model.element.PackageElement
+import javax.lang.model.element.TypeElement
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.netbeans.api.java.source.ClasspathInfo
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.ElementHandle
+import org.netbeans.api.java.source.SourceUtils
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.project.Project
+import org.openide.filesystems.FileObject
+
+class TypeElementSearcher(val fqName: String, val project: Project) : Task<CompilationController> {
+
+ var element: ElemHandle<TypeElement>? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = info.elements.getTypeElement(fqName) ?: return
+ element = ElemHandle.create(elem, project)
+ }
+}
+
+class TypeElementHandleSearcher(val fqName: String, val project: Project) : Task<CompilationController> {
+
+ var element: ElementHandle<TypeElement>? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = info.elements.getTypeElement(fqName) ?: return
+ element = ElementHandle.create(elem)
+ }
+}
+
+class PackageElementSearcher(val fqName: String, val project: Project) : Task<CompilationController> {
+
+ var `package`: ElemHandle<PackageElement>? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = info.elements.getPackageElement(fqName) ?: return
+ `package` = ElemHandle.create(elem, project)
+ }
+}
+
+class ClassIdComputer(val handle: ElemHandle<TypeElement>) : Task<CompilationController> {
+
+ var classId: ClassId? = null
+
+ private fun computeClassId(classBinding: TypeElement): ClassId? {
+ val container = classBinding.enclosingElement
+
+ if (container.kind != ElementKind.PACKAGE) {
+ val parentClassId = computeClassId(container as TypeElement) ?: return null
+ return parentClassId.createNestedClassId(Name.identifier(classBinding.simpleName.toString()))
+ }
+
+ val fqName = classBinding.qualifiedName.toString()
+ return ClassId.topLevel(FqName(fqName))
+ }
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = handle.resolve(info) ?: return
+ classId = computeClassId(elem as TypeElement)
+ }
+}
+
+class ElementSearcher(val offset: Int) : Task<CompilationController> {
+
+ var element: ElementHandle<*>? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val treePath = info.treeUtilities.pathFor(offset)
+ val elem = info.trees.getElement(treePath) ?: return
+
+ if (elem.kind != ElementKind.LOCAL_VARIABLE) element = ElementHandle.create(elem)
+ }
+}
+
+class ElementSimpleNameSearcher(val element: ElemHandle<*>) : Task<CompilationController> {
+
+ var simpleName: String = ""
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = element.resolve(info) ?: return
+ simpleName = elem.simpleName.toString()
+ }
+}
+
+class ElementHandleSimpleNameSearcher(val element: ElementHandle<*>) : Task<CompilationController> {
+
+ var simpleName: String? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val elem = element.resolve(info) ?: return
+ simpleName = elem.simpleName.toString()
+ }
+}
+
+class IsDeprecatedSearcher(val element: ElemHandle<*>?) : Task<CompilationController> {
+
+ var isDeprecated = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ if (element == null) return
+ val elem = element.resolve(info) ?: return
+
+ isDeprecated = info.elements.isDeprecated(elem)
+ }
+}
+
+class JavaDocSearcher(val element: ElemHandle<*>?) : Task<CompilationController> {
+
+ var javaDoc: Doc? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ if (element == null) return
+ val elem = element.resolve(info) ?: return
+
+ javaDoc = info.elementUtilities.javaDocFor(elem)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotation.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotation.kt
new file mode 100644
index 0000000..d4b4891
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotation.kt
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+import javax.lang.model.type.DeclaredType
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaAnnotation(val project: Project, val handle: TypeMirrorHandle<DeclaredType>,
+ override val arguments: Collection<JavaAnnotationArgument>) :
+ JavaAnnotation, JavaElement {
+
+ override val classId: ClassId?
+ get() = handle.computeClassId(project)
+
+ override fun resolve(): JavaClass? = handle.getJavaClass(project)
+ override fun hashCode(): Int = handle.getHashCode(project)
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is NetBeansJavaAnnotation) return false
+
+ return handle.isEqual(other.handle, project)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotationArgument.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotationArgument.kt
new file mode 100644
index 0000000..2e46f99
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotationArgument.kt
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+open class NetBeansJavaAnnotationArgument(private val fqName: FqName) : JavaAnnotationArgument, JavaElement {
+ override val name
+ get() = Name.identifier(fqName.shortName().asString())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotationAsAnnotationArgument.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotationAsAnnotationArgument.kt
new file mode 100644
index 0000000..2def080
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaAnnotationAsAnnotationArgument.kt
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationAsAnnotationArgument
+import org.jetbrains.kotlin.name.Name
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+import javax.lang.model.type.DeclaredType
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaAnnotationAsAnnotationArgument(val project: Project,
+ override val name: Name,
+ val typeHandle: TypeMirrorHandle<DeclaredType>,
+ val args: List<JavaAnnotationArgument>) :
+ JavaAnnotationAsAnnotationArgument {
+
+ override fun getAnnotation() = NetBeansJavaAnnotation(project, typeHandle, args)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaArrayAnnotationArgument.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaArrayAnnotationArgument.kt
new file mode 100644
index 0000000..be85076
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaArrayAnnotationArgument.kt
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaArrayAnnotationArgument
+import org.jetbrains.kotlin.name.Name
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaArrayAnnotationArgument(val args: List<JavaAnnotationArgument>, override val name: Name) : JavaArrayAnnotationArgument {
+ override fun getElements() = args
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaArrayType.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaArrayType.kt
new file mode 100644
index 0000000..f6b798e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaArrayType.kt
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaArrayType
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaArrayType(handle: TypeMirrorHandle<*>, project: Project) :
+ NetBeansJavaType(handle, project), JavaArrayType {
+ override val componentType
+ get() = handle.getComponentType(project)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClass.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClass.kt
new file mode 100644
index 0000000..5bd426a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClass.kt
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import javax.lang.model.element.ElementKind
+import org.jetbrains.kotlin.descriptors.Visibility
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
+import org.jetbrains.kotlin.load.java.structure.JavaConstructor
+import org.jetbrains.kotlin.load.java.structure.JavaField
+import org.jetbrains.kotlin.load.java.structure.JavaMethod
+import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
+import org.jetbrains.kotlin.name.FqName
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+import javax.lang.model.element.TypeElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+class NetBeansJavaClass(elementHandle: ElemHandle<TypeElement>, project: Project) :
+ NetBeansJavaClassifier<TypeElement>(elementHandle, project), JavaClass {
+
+ override val name
+ get() = elementHandle.getName(project)
+
+ override val fqName: FqName?
+ get() = elementHandle.getFqName()
+
+ override val supertypes: Collection<JavaClassifierType>
+ get() = elementHandle.getSuperTypes(project)
+
+ override val innerClasses: Collection<JavaClass>
+ get() = elementHandle.getInnerClasses(project)
+
+ override val outerClass: JavaClass?
+ get() = elementHandle.getOuterClass(project)
+
+ override val methods: Collection<JavaMethod>
+ get() = elementHandle.getMethods(project, this)
+
+ override val constructors: Collection<JavaConstructor>
+ get() = elementHandle.getConstructors(project, this)
+
+ override val fields: Collection<JavaField>
+ get() = elementHandle.getFields(project, this)
+
+ override val visibility: Visibility
+ get() = elementHandle.getVisibility(project)
+
+ override val typeParameters: List<JavaTypeParameter>
+ get() = elementHandle.getTypeParameters(project)
+
+ override val isInterface
+ get() = elementHandle.kind == ElementKind.INTERFACE
+ override val isAnnotationType
+ get() = elementHandle.kind == ElementKind.ANNOTATION_TYPE
+ override val isEnum
+ get() = elementHandle.kind == ElementKind.ENUM
+ override val isAbstract
+ get() = elementHandle.isAbstract(project)
+ override val isStatic
+ get() = elementHandle.isStatic(project)
+ override val isFinal
+ get() = elementHandle.isFinal(project)
+
+ override val lightClassOriginKind = null
+
+ override fun toString(): String = elementHandle.qualifiedName
+
+ fun presentation(): String {
+ val visibility = visibility.displayName
+ val final = if (isFinal) " final" else ""
+ val cl = if (isInterface) " interface" else if (isEnum) " enum" else " class"
+
+ return "$visibility$final$cl ${elementHandle.qualifiedName}"
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassObjectAnnotationArgument.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassObjectAnnotationArgument.kt
new file mode 100644
index 0000000..9646e68
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassObjectAnnotationArgument.kt
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import javax.lang.model.type.TypeMirror
+import org.jetbrains.kotlin.load.java.structure.JavaClassObjectAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.name.Name
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaClassObjectAnnotationArgument(private val typeMirror: TypeMirror, override val name: Name,
+ val project: Project) : JavaClassObjectAnnotationArgument {
+ override fun getReferencedType(): JavaType {
+ val handle = TypeMirrorHandle.create(typeMirror)
+ return NetBeansJavaType.create(handle, project)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassifier.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassifier.kt
new file mode 100644
index 0000000..1610049
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassifier.kt
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner
+import org.jetbrains.kotlin.load.java.structure.JavaClassifier
+import org.jetbrains.kotlin.name.FqName
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+import javax.lang.model.element.Element
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+abstract class NetBeansJavaClassifier<T : Element>(elementHandle: ElemHandle<T>, project: Project) :
+ NetBeansJavaElement<T>(elementHandle, project), JavaClassifier, JavaAnnotationOwner {
+
+ override val annotations: Collection<JavaAnnotation>
+ get() = elementHandle.getAnnotations(project)
+
+ override val isDeprecatedInJavaDoc
+ get() = elementHandle.isDeprecated(project)
+
+ override fun findAnnotation(fqName: FqName) = elementHandle.getAnnotation(project, fqName)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassifierType.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassifierType.kt
new file mode 100644
index 0000000..6654d30
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaClassifierType.kt
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import javax.lang.model.type.TypeKind
+import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaClassifierType(handle: TypeMirrorHandle<*>, project: Project) :
+ NetBeansJavaType(handle, project), JavaClassifierType {
+
+ override val presentableText
+ get() = handle.getName(project)
+ override val canonicalText
+ get() = handle.getName(project)
+
+ override val isRaw: Boolean
+ get() = if (handle.kind == TypeKind.DECLARED) handle.isRaw(project) else false
+
+ override val typeArguments: List<JavaType>
+ get() = if (handle.kind == TypeKind.DECLARED) handle.getTypeArguments(project) else emptyList()
+
+ override val classifier
+ get() = when (handle.kind) {
+ TypeKind.DECLARED -> handle.getJavaClass(project)
+ TypeKind.TYPEVAR -> NetBeansJavaTypeParameter(handle.toElemHandle(project), project)
+ else -> null
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaConstructor.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaConstructor.kt
new file mode 100644
index 0000000..f4d0309
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaConstructor.kt
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaConstructor
+import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
+import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+import javax.lang.model.element.ExecutableElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+class NetBeansJavaConstructor(elementHandle: ElemHandle<ExecutableElement>, containingClass: JavaClass, project: Project) :
+ NetBeansJavaMember<ExecutableElement>(elementHandle, containingClass, project), JavaConstructor {
+
+ override val valueParameters: List<JavaValueParameter>
+ get() = elementHandle.getValueParameters(project)
+
+ override val typeParameters: List<JavaTypeParameter>
+ get() = elementHandle.getTypeParameters(project)
+
+ override fun presentation() = "$name${valueParameters.joinToString(prefix = "(", postfix = ")") { "${it.type} ${it.name}" }}"
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaElement.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaElement.kt
new file mode 100644
index 0000000..5861ee6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaElement.kt
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+import javax.lang.model.element.Element
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+abstract class NetBeansJavaElement<T : Element>(val elementHandle: ElemHandle<T>,
+ val project: Project) : JavaElement {
+
+ override fun hashCode() = elementHandle.hashCode()
+
+ override fun equals(other: Any?) = (other as? NetBeansJavaElement<*>)?.elementHandle == elementHandle
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaField.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaField.kt
new file mode 100644
index 0000000..cf685e6
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaField.kt
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import javax.lang.model.element.ElementKind
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaField
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.project.Project
+import javax.lang.model.element.VariableElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+class NetBeansJavaField(elementHandle: ElemHandle<VariableElement>, containingClass: JavaClass, project: Project) :
+ NetBeansJavaMember<VariableElement>(elementHandle, containingClass, project), JavaField {
+
+ override val isEnumEntry
+ get() = elementHandle.kind == ElementKind.ENUM_CONSTANT
+ override val type: JavaType
+ get() = elementHandle.getFieldType(project)
+
+ override fun presentation() = "$type $name"
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaLiteralAnnotationArgument.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaLiteralAnnotationArgument.kt
new file mode 100644
index 0000000..2e342eb
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaLiteralAnnotationArgument.kt
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaLiteralAnnotationArgument
+import org.jetbrains.kotlin.name.Name
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaLiteralAnnotationArgument(override val value: Any,
+ override val name: Name) : JavaLiteralAnnotationArgument
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaMember.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaMember.kt
new file mode 100644
index 0000000..7521411
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaMember.kt
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.descriptors.Visibility
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaMember
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.project.Project
+import javax.lang.model.element.Element
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+abstract class NetBeansJavaMember<T : Element>(elementHandle: ElemHandle<T>, override val containingClass: JavaClass, project: Project) :
+ NetBeansJavaElement<T>(elementHandle, project), JavaMember {
+
+ override val annotations: Collection<JavaAnnotation>
+ get() = elementHandle.getAnnotations(project)
+
+ override val visibility: Visibility
+ get() = elementHandle.getVisibility(project)
+
+ override val name: Name
+ get() = elementHandle.getName(project)
+
+ override val isDeprecatedInJavaDoc
+ get() = elementHandle.isDeprecated(project)
+ override val isAbstract
+ get() = elementHandle.isAbstract(project)
+ override val isStatic
+ get() = elementHandle.isStatic(project)
+ override val isFinal
+ get() = elementHandle.isFinal(project)
+
+ override fun findAnnotation(fqName: FqName): JavaAnnotation? = elementHandle.getAnnotation(project, fqName)
+
+ abstract fun presentation(): String
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaMethod.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaMethod.kt
new file mode 100644
index 0000000..7b87bce
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaMethod.kt
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.java.structure.JavaMethod
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
+import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+import javax.lang.model.element.ExecutableElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+class NetBeansJavaMethod(elementHandle: ElemHandle<ExecutableElement>, containingClass: JavaClass, project: Project) :
+ NetBeansJavaMember<ExecutableElement>(elementHandle, containingClass, project), JavaMethod {
+
+ override val valueParameters: List<JavaValueParameter>
+ get() = elementHandle.getValueParameters(project)
+
+ override val returnType: JavaType
+ get() = elementHandle.getReturnType(project)
+
+ override val hasAnnotationParameterDefaultValue: Boolean
+ get() = elementHandle.hasAnnotationParameterDefaultValue(project)
+
+ override val typeParameters: List<JavaTypeParameter>
+ get() = elementHandle.getTypeParameters(project)
+
+ override fun presentation() = "$returnType $name${valueParameters.joinToString(prefix = "(", postfix = ")") { "${it.type} ${it.name}" }}"
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPackage.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPackage.kt
new file mode 100644
index 0000000..a7bb3e4
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPackage.kt
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import java.util.Collections
+import javax.lang.model.element.PackageElement
+import org.jetbrains.kotlin.load.java.structure.JavaElement
+import org.jetbrains.kotlin.load.java.structure.JavaPackage
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Aug 29, 2016
+*/
+
+class NetBeansJavaPackage(private val packages: List<ElemHandle<PackageElement>>, val project: Project) :
+ JavaPackage, JavaElement {
+
+ constructor(pack: ElemHandle<PackageElement>, project: Project) : this(Collections.singletonList(pack), project)
+
+ override val fqName: FqName
+ get() = packages.first().getFqName(project)
+
+ override val subPackages: Collection<JavaPackage>
+ get() = getSubPackages(project)
+
+ override fun getClasses(nameFilter: (Name) -> Boolean) =
+ packages.getClasses(project, nameFilter)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPrimitiveType.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPrimitiveType.kt
new file mode 100644
index 0000000..7e479fc
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPrimitiveType.kt
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.builtins.PrimitiveType
+import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
+import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
+import org.jetbrains.kotlin.resolve.lang.java.getName
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaPrimitiveType(handle: TypeMirrorHandle<*>, project: Project) :
+ NetBeansJavaType(handle, project), JavaPrimitiveType {
+
+ override val type: PrimitiveType?
+ get() {
+ val text = handle.getName(project)
+ return if ("void" == text) null else JvmPrimitiveType.get(text).primitiveType
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPropertyInitializerEvaluator.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPropertyInitializerEvaluator.kt
new file mode 100644
index 0000000..d459955
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaPropertyInitializerEvaluator.kt
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.load.java.structure.JavaField
+import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluator
+import org.jetbrains.kotlin.resolve.constants.ConstantValue
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaPropertyInitializerEvaluator : JavaPropertyInitializerEvaluator {
+
+ override fun getInitializerConstant(field: JavaField, descriptor: PropertyDescriptor): ConstantValue<*>? = null
+ override fun isNotNullCompileTimeConstant(field: JavaField): Boolean = false
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaReferenceAnnotationArgument.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaReferenceAnnotationArgument.kt
new file mode 100644
index 0000000..bffc25a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaReferenceAnnotationArgument.kt
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaEnumValueAnnotationArgument
+import org.jetbrains.kotlin.load.java.structure.JavaField
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.ElemHandle
+import javax.lang.model.element.VariableElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaReferenceAnnotationArgument(val handle: ElemHandle<VariableElement>, val project: Project) :
+ NetBeansJavaAnnotationArgument(FqName(handle.getSimpleName(project))), JavaEnumValueAnnotationArgument {
+ override fun resolve(): JavaField {
+ val containingClass = handle.getContainingClass(project)
+ return NetBeansJavaField(handle, NetBeansJavaClass(containingClass, project), project)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaType.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaType.kt
new file mode 100644
index 0000000..8096ba0
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaType.kt
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import javax.lang.model.type.TypeKind
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+abstract class NetBeansJavaType(val handle: TypeMirrorHandle<*>,
+ val project: Project) : JavaType, JavaAnnotationOwner {
+
+ companion object {
+ @JvmStatic
+ fun create(typeHandle: TypeMirrorHandle<*>, project: Project): NetBeansJavaType = when {
+ typeHandle.kind.isPrimitive || typeHandle.kind == TypeKind.VOID -> NetBeansJavaPrimitiveType(typeHandle, project)
+ typeHandle.kind == TypeKind.ARRAY -> NetBeansJavaArrayType(typeHandle, project)
+ typeHandle.kind == TypeKind.DECLARED || typeHandle.kind == TypeKind.TYPEVAR -> NetBeansJavaClassifierType(typeHandle, project)
+ typeHandle.kind == TypeKind.WILDCARD -> NetBeansJavaWildcardType(typeHandle, project)
+ else -> throw UnsupportedOperationException("Unsupported NetBeans type ${typeHandle.getName(project)}")
+ }
+ }
+
+ override val isDeprecatedInJavaDoc = false
+
+ override val annotations: Collection<JavaAnnotation>
+ get() = handle.getAnnotations(project)
+
+ override fun findAnnotation(fqName: FqName): JavaAnnotation? = handle.getAnnotation(project, fqName)
+ override fun hashCode(): Int = handle.getHashCode(project)
+ override fun equals(other: Any?): Boolean = other is NetBeansJavaType && handle.isEqual(other.handle, project)
+ override fun toString() = handle.getName(project)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaTypeParameter.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaTypeParameter.kt
new file mode 100644
index 0000000..7b4cc27
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaTypeParameter.kt
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
+import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.resolve.lang.java.*
+import javax.lang.model.element.TypeParameterElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaTypeParameter(elementHandle: ElemHandle<TypeParameterElement>, project: Project) :
+ NetBeansJavaClassifier<TypeParameterElement>(elementHandle, project), JavaTypeParameter {
+
+ override val name: Name
+ get() = elementHandle.getName(project)
+
+ override val upperBounds: Collection<JavaClassifierType>
+ get() = elementHandle.getUpperBounds(project)
+
+ override val annotations: Collection<JavaAnnotation>
+ get() = emptyList()
+
+ override fun findAnnotation(fqName: FqName): JavaAnnotation? = null
+ override fun toString(): String = name.asString()
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is NetBeansJavaTypeParameter) return false
+
+ val bound = upperBounds.firstOrNull()?.canonicalText ?: ""
+ val otherBound = other.upperBounds.firstOrNull()?.canonicalText ?: ""
+
+ val fullName = "$name $bound"
+ val otherFullName = "${other.name} $otherBound"
+
+ return fullName == otherFullName
+ }
+
+ override fun hashCode(): Int {
+ val bound = upperBounds.firstOrNull()?.canonicalText ?: ""
+
+ return "$name $bound".hashCode()
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaValueParameter.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaValueParameter.kt
new file mode 100644
index 0000000..97e0c80
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaValueParameter.kt
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.project.Project
+import javax.lang.model.element.VariableElement
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaValueParameter(elementHandle: ElemHandle<VariableElement>, project: Project,
+ private val parameterName: String,
+ override val isVararg: Boolean) :
+ NetBeansJavaElement<VariableElement>(elementHandle, project), JavaValueParameter {
+
+ override val name
+ get() = Name.identifier(parameterName)
+
+ override val isDeprecatedInJavaDoc = false
+
+ override val type: JavaType
+ get() = NetBeansJavaType.create(elementHandle.typeMirrorHandle, project)
+
+ override val annotations: Collection<JavaAnnotation>
+ get() = emptyList()
+
+ override fun findAnnotation(fqName: FqName) = null
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaWildcardType.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaWildcardType.kt
new file mode 100644
index 0000000..6d3ea0e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/structure/NetBeansJavaWildcardType.kt
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java.structure
+
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.load.java.structure.JavaWildcardType
+import org.jetbrains.kotlin.resolve.lang.java.*
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Sep 7, 2016
+*/
+
+class NetBeansJavaWildcardType(handle: TypeMirrorHandle<*>, project: Project) : NetBeansJavaType(handle, project), JavaWildcardType {
+
+ override val bound: JavaType?
+ get() = handle.getBound(project)
+
+ override val isExtends
+ get() = handle.isExtends(project)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/typeSearchers.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/typeSearchers.kt
new file mode 100644
index 0000000..842607e
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/java/typeSearchers.kt
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.resolve.lang.java
+
+import javax.lang.model.element.TypeElement
+import javax.lang.model.type.ArrayType
+import javax.lang.model.type.DeclaredType
+import javax.lang.model.type.WildcardType
+import org.jetbrains.kotlin.load.java.structure.JavaType
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaType
+import org.netbeans.api.java.source.CompilationController
+import org.netbeans.api.java.source.Task
+import org.netbeans.api.java.source.TypeMirrorHandle
+import org.netbeans.api.project.Project
+
+class TypeNameSearcher(val handle: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ lateinit var name: String
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: throw UnsupportedOperationException("$handle doesn't exist'")
+ name = type.toString()
+ }
+}
+
+class BoundSearcher(val handle: TypeMirrorHandle<*>,
+ val project: Project) : Task<CompilationController> {
+
+ var bound: JavaType? = null
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: return
+ val boundMirror = (type as WildcardType).extendsBound ?: type.superBound
+
+ bound = if (boundMirror != null) NetBeansJavaType.create(TypeMirrorHandle.create(boundMirror), project) else null
+ }
+}
+
+class IsExtendsSearcher(val handle: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ var isExtends = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: return
+ isExtends = (type as WildcardType).extendsBound != null
+ }
+}
+
+class ComponentTypeSearcher(val handle: TypeMirrorHandle<*>,
+ val project: Project) : Task<CompilationController> {
+
+ lateinit var componentType: JavaType
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: throw UnsupportedOperationException("Component type not found")
+ val componentTypeHandle = TypeMirrorHandle.create((type as ArrayType).componentType)
+ componentType = NetBeansJavaType.create(componentTypeHandle, project)
+ }
+}
+
+class IsRawSearcher(val handle: TypeMirrorHandle<*>) : Task<CompilationController> {
+
+ var isRaw = false
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) as? DeclaredType ?: return
+ val element = type.asElement() as TypeElement
+ if (element.typeParameters.isEmpty()) return
+
+ isRaw = type.typeArguments.isEmpty()
+ }
+}
+
+class TypeArgumentsSearcher(val handle: TypeMirrorHandle<*>,
+ val project: Project) : Task<CompilationController> {
+
+ val typeArguments = arrayListOf<JavaType>()
+
+ override fun run(info: CompilationController) {
+ info.toResolvedPhase()
+
+ val type = handle.resolve(info) ?: return
+ val args = (type as DeclaredType).typeArguments
+ .map { NetBeansJavaType.create(TypeMirrorHandle.create(it), project) }
+ typeArguments.addAll(args)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/kotlin/NetBeansVirtualFileFinder.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/kotlin/NetBeansVirtualFileFinder.kt
new file mode 100644
index 0000000..ed0ea93
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/resolve/lang/kotlin/NetBeansVirtualFileFinder.kt
@@ -0,0 +1,169 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.resolve.lang.kotlin
+
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.search.GlobalSearchScope
+import java.io.InputStream
+import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
+import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
+import org.jetbrains.kotlin.model.KotlinEnvironment
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper.getFullClassPath
+import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder
+import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClassFinder
+import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinderFactory
+import org.jetbrains.kotlin.name.ClassId
+import org.netbeans.api.project.Project
+import org.jetbrains.kotlin.load.java.structure.JavaClass
+import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
+import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
+import org.jetbrains.kotlin.log.KotlinLogger
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
+import org.jetbrains.kotlin.resolve.lang.java.computeClassId
+import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
+import org.jetbrains.kotlin.resolve.lang.java.structure.NetBeansJavaClass
+import org.openide.filesystems.FileObject
+import org.openide.filesystems.FileStateInvalidException
+
+class NetBeansVirtualFileFinder(private val project: Project,
+ private val scope: GlobalSearchScope) : VirtualFileKotlinClassFinder() {
+
+ val index: JvmDependenciesIndex
+ get() = KotlinEnvironment.getEnvironment(project).index
+
+ private fun isClassFileName(name: String?): Boolean {
+ if (name == null) return false
+
+ val suffixClass = ".class".toCharArray()
+ val suffixClass2 = ".CLASS".toCharArray()
+ val nameLength = name.length
+ val suffixLength = suffixClass.size
+ if (nameLength < suffixLength) return false
+
+ for (i in 0 until suffixLength) {
+ val c = name[nameLength - i - 1]
+ val suffixIndex = suffixLength - i - 1
+
+ if (c != suffixClass[suffixIndex] && c != suffixClass2[suffixIndex]) return false
+ }
+ return true
+ }
+
+ private fun getJarPath(file: FileObject) = file.fileSystem?.displayName
+
+ override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? {
+ val proxy = project.getFullClassPath()
+
+ val classFqName = if (classId.isNestedClass) {
+ val className = classId.shortClassName.asString()
+ val fqName = classId.asSingleFqName().asString()
+ StringBuilder(fqName.substring(0,
+ fqName.length - className.length - 1).replace(".", "/"))
+ .append("$").append(className).append(".class").toString()
+ } else "${classId.asSingleFqName().asString().replace(".", "/")}.class"
+
+ val resource = proxy?.findResource(classFqName) ?: return if (isClassFileName(classFqName)) {
+ KotlinEnvironment.getEnvironment(project).getVirtualFile(classFqName)
+ } else throw IllegalArgumentException("Virtual file not found for $classFqName")
+
+ val path = resource.toURL().path
+ if (path.contains("!/")) {
+ try {
+ val pathToJar = getJarPath(resource) ?: return null
+ val splittedPath = path.split("!/")
+ if (splittedPath.size < 2) return null
+
+ return KotlinEnvironment.Companion.getEnvironment(project).getVirtualFileInJar(pathToJar, splittedPath[1])
+ } catch (ex: FileStateInvalidException) {
+ KotlinLogger.INSTANCE.logException("Can't get file in jar", ex)
+ return null
+ }
+ }
+
+ if (isClassFileName(path)) {
+ return KotlinEnvironment.Companion.getEnvironment(project).getVirtualFile(path)
+ } else throw IllegalArgumentException("Virtual file not found for $path")
+ }
+
+ private fun classFileName(jClass: JavaClass): String {
+ val outerClass = jClass.outerClass ?: return jClass.name.asString()
+
+ return "${classFileName(outerClass)}$${jClass.name.asString()}"
+ }
+
+ override fun findKotlinClass(javaClass: JavaClass): KotlinJvmBinaryClass? {
+ javaClass.fqName ?: return null
+ val classId = (javaClass as NetBeansJavaClass).elementHandle.computeClassId(project) ?: return null
+ var file: VirtualFile? = findVirtualFileWithHeader(classId) ?: return null
+
+ if (javaClass.outerClass != null) {
+ val classFileName = "${classFileName(javaClass)}.class"
+ file = file!!.parent.findChild(classFileName)
+ if (file != null) {
+ throw IllegalStateException("Virtual file not found")
+ }
+ }
+ return KotlinBinaryClassCache.Companion.getKotlinBinaryClass(file!!, null)
+ }
+
+ override fun findBuiltInsData(packageFqName: FqName): InputStream? {
+ val fileName = BuiltInSerializerProtocol.getBuiltInsFileName(packageFqName)
+
+ val classId = ClassId(packageFqName, Name.special("<builtins-metadata>"))
+
+ return index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
+ dir.findChild(fileName)?.check(VirtualFile::isValid)
+ }?.check { it in scope }?.inputStream
+ }
+
+ override fun findMetadata(classId: ClassId): InputStream? {
+ assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
+
+ return findBinaryClass(
+ classId,
+ "${classId.shortClassName.asString()}${MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION}")?.inputStream
+ }
+
+ override fun hasMetadataPackage(fqName: FqName): Boolean {
+ var found = false
+
+ val index = KotlinEnvironment.getEnvironment(project).index
+
+ index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
+ found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION }
+ !found
+ })
+
+ return found
+ }
+
+ private fun findBinaryClass(classId: ClassId, fileName: String): VirtualFile? =
+ index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ ->
+ dir.findChild(fileName)?.check(VirtualFile::isValid)
+ }?.check { it in scope }
+
+ fun <T : Any> T.check(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
+
+}
+
+class NetBeansVirtualFileFinderFactory(private val project: Project) : JvmVirtualFileFinderFactory {
+ override fun create(scope: GlobalSearchScope): JvmVirtualFileFinder = NetBeansVirtualFileFinder(project, scope)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/GoToKotlinTypeProvider.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/GoToKotlinTypeProvider.kt
new file mode 100644
index 0000000..5f2785a
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/GoToKotlinTypeProvider.kt
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.search
+
+import java.io.File
+import org.jetbrains.kotlin.navigation.netbeans.openFileAtOffset
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.ui.OpenProjects
+import org.netbeans.spi.quicksearch.SearchProvider
+import org.netbeans.spi.quicksearch.SearchRequest
+import org.netbeans.spi.quicksearch.SearchResponse
+import org.openide.filesystems.FileUtil
+
+class GoToKotlinTypeProvider : SearchProvider {
+
+ override fun evaluate(request: SearchRequest, response: SearchResponse) {
+ OpenProjects.getDefault().openProjects
+ .flatMap { KotlinTypeSearcher.searchDeclaration(it, request.text) }
+ .forEach {
+ val file = it.first
+ it.second.forEach {
+ val html = "${it.name} (${file.packageFqName.asString()})"
+ response.addResult(action@{
+ val f = File(file.virtualFile.path)
+ val fo = FileUtil.toFileObject(f) ?: return@action
+
+ val doc = ProjectUtils.getDocumentFromFileObject(fo) ?: return@action
+ openFileAtOffset(doc, it.textRange.startOffset)
+ }, html)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/KotlinTypeSearcher.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/KotlinTypeSearcher.kt
new file mode 100644
index 0000000..d1665c0
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/KotlinTypeSearcher.kt
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.search
+
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.Project
+
+object KotlinTypeSearcher {
+
+ private fun findDeclarationsInFile(ktFile: KtFile,
+ fqName: String) = ktFile.declarations
+ .filter { it.name?.contains(fqName) == true }
+
+ fun searchDeclaration(project: Project, fqName: String) = ProjectUtils.getSourceFilesWithDependencies(project)
+ .mapNotNull {
+ val declarationsInFile = findDeclarationsInFile(it, fqName)
+ if (declarationsInFile.isNotEmpty()) {
+ it to findDeclarationsInFile(it, fqName)
+ }
+ else null
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/PublicFunctionsVisitor.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/PublicFunctionsVisitor.kt
new file mode 100644
index 0000000..be453c3
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/search/PublicFunctionsVisitor.kt
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.search
+
+import org.jetbrains.kotlin.psi.*
+
+class PublicFunctionsVisitor(private val predicate: (String) -> Boolean) : KtVisitorVoid() {
+
+ val publicFunctions = hashSetOf<String>()
+
+ override fun visitNamedFunction(function: KtNamedFunction) {
+ val functionName = function.name ?: return
+ val fqName = function.fqName?.asString() ?: return
+
+ if (predicate(functionName) && function.modifierList == null) {
+ publicFunctions.add(fqName)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinClassStructureItem.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinClassStructureItem.kt
new file mode 100644
index 0000000..af49e82
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinClassStructureItem.kt
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.structurescanner
+
+import javax.swing.ImageIcon
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.netbeans.modules.csl.api.ElementKind
+import org.netbeans.modules.csl.api.HtmlFormatter
+import org.netbeans.modules.csl.api.Modifier
+import org.netbeans.modules.csl.api.StructureItem
+import org.openide.util.ImageUtilities
+
+class KotlinClassStructureItem(private val psiElement: KtClassOrObject,
+ private val isLeaf: Boolean,
+ private val context: BindingContext) : StructureItem {
+
+ override fun getName(): String {
+ val className = psiElement.name
+ val superTypes = psiElement.superTypeListEntries.let {
+ if (it.isNotEmpty()) it.joinToString(prefix = "::") { it.text } else ""
+ }
+
+ return "$className$superTypes"
+ }
+
+ override fun getSortText() = psiElement.name
+ override fun getHtml(formatter: HtmlFormatter) = name
+ override fun getElementHandle() = null
+ override fun getKind() = ElementKind.CLASS
+ override fun getModifiers() = emptySet<Modifier>()
+ override fun isLeaf() = isLeaf
+ override fun getPosition() = psiElement.textRange.startOffset.toLong()
+ override fun getEndPosition() = psiElement.textRange.endOffset.toLong()
+ override fun getCustomIcon() = ImageIcon(ImageUtilities.loadImage("org/jetbrains/kotlin/completionIcons/class.png"))
+
+ override fun getNestedItems() = psiElement.declarations.mapNotNull {
+ when (it) {
+ is KtClass -> KotlinClassStructureItem(it, true, context)
+ is KtNamedFunction -> KotlinFunctionStructureItem(it, true, context)
+ is KtProperty -> KotlinPropertyStructureItem(it, true, context)
+ else -> null
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinFoldingVisitor.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinFoldingVisitor.kt
new file mode 100644
index 0000000..693d236
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinFoldingVisitor.kt
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.structurescanner
+
+import com.intellij.openapi.util.TextRange
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiComment
+import com.intellij.psi.util.PsiTreeUtil
+import org.jetbrains.kotlin.psi.*
+import org.netbeans.modules.csl.api.OffsetRange
+
+class KotlinFoldingVisitor(val ktFile: KtFile) : KtVisitorVoid() {
+
+ private val comments = arrayListOf<OffsetRange>()
+ private val imports = arrayListOf<OffsetRange>()
+ private val codeBlocks = arrayListOf<OffsetRange>()
+
+ fun computeFolds(): Map<String, List<OffsetRange>> {
+ ktFile.acceptChildren(this)
+
+ val found: Collection<PsiElement> = PsiTreeUtil.findChildrenOfType(ktFile, PsiComment::class.java)
+ found.mapTo(comments) { it.textRange.toOffsetRange() }
+
+ return mapOf("comments" to comments,
+ "codeblocks" to codeBlocks,
+ "imports" to imports)
+ }
+
+ override fun visitElement(element: PsiElement) = element.acceptChildren(this)
+
+ override fun visitClassBody(body: KtClassBody) {
+ codeBlocks.add(body.textRange.toOffsetRange())
+ super.visitClassBody(body)
+ }
+
+ override fun visitBlockExpression(expression: KtBlockExpression) {
+ codeBlocks.add(expression.textRange.toOffsetRange())
+ super.visitBlockExpression(expression)
+ }
+
+ override fun visitImportList(importList: KtImportList) {
+ imports.add(importList.textRange.toOffsetRange())
+ super.visitImportList(importList)
+ }
+
+ private fun TextRange.toOffsetRange() = OffsetRange(startOffset, endOffset)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinFunctionStructureItem.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinFunctionStructureItem.kt
new file mode 100644
index 0000000..5ec9773
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinFunctionStructureItem.kt
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.structurescanner
+
+import com.intellij.psi.PsiComment
+import com.intellij.psi.PsiWhiteSpace
+import com.intellij.psi.util.PsiTreeUtil
+import javax.swing.ImageIcon
+import org.jetbrains.kotlin.psi.KtNamedFunction
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
+import org.netbeans.modules.csl.api.ElementKind
+import org.netbeans.modules.csl.api.HtmlFormatter
+import org.netbeans.modules.csl.api.Modifier
+import org.netbeans.modules.csl.api.StructureItem
+import org.openide.util.ImageUtilities
+
+class KotlinFunctionStructureItem(private val function: KtNamedFunction,
+ private val isLeaf: Boolean,
+ private val context: BindingContext) : StructureItem {
+
+ override fun getName(): String {
+ val name = function.name
+ val valueParameters = function.valueParameters.joinToString(prefix = "(", postfix = ")") { it.text }
+
+ val receiver = function.receiverTypeReference?.text?.let { "$it." } ?: ""
+
+ val returnType = (context[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? SimpleFunctionDescriptor)
+ ?.let { it.returnType
+ ?.takeIf { it.toString() != "Unit" }
+ ?.let { ": $it" }
+ }
+ ?: function.colon?.let {
+ val sibling = PsiTreeUtil.skipSiblingsForward(it, PsiWhiteSpace::class.java, PsiComment::class.java)
+ if (sibling != null) {
+ ": ${sibling.text}"
+ } else ""
+ } ?: ""
+
+ return "$receiver$name$valueParameters$returnType"
+ }
+
+ override fun getSortText() = function.name
+ override fun getHtml(formatter: HtmlFormatter) = name
+ override fun getElementHandle() = null
+ override fun getKind() = ElementKind.METHOD
+ override fun getModifiers() = emptySet<Modifier>()
+ override fun isLeaf() = isLeaf
+ override fun getNestedItems() = listOf<StructureItem>()
+ override fun getPosition() = function.textRange.startOffset.toLong()
+ override fun getEndPosition() = function.textRange.endOffset.toLong()
+ override fun getCustomIcon() = ImageIcon(ImageUtilities.loadImage("org/jetbrains/kotlin/completionIcons/method.png"))
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinPropertyStructureItem.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinPropertyStructureItem.kt
new file mode 100644
index 0000000..09ba443
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinPropertyStructureItem.kt
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.structurescanner
+
+import javax.swing.ImageIcon
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.descriptors.VariableDescriptor
+import org.netbeans.modules.csl.api.ElementKind
+import org.netbeans.modules.csl.api.HtmlFormatter
+import org.netbeans.modules.csl.api.Modifier
+import org.netbeans.modules.csl.api.StructureItem
+import org.openide.util.ImageUtilities
+
+class KotlinPropertyStructureItem(private val property: KtProperty,
+ private val isLeaf: Boolean,
+ private val context: BindingContext) : StructureItem {
+
+ override fun getName(): String {
+ val name = property.name
+ val type = property.typeReference?.text?.let { ": $it" } ?:
+ (context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptor)
+ ?.let {
+ it.type.takeIf { it.toString() != "Unit" }
+ ?.let { ": $it" }
+ } ?: ""
+
+ return "$name$type"
+ }
+
+ override fun getSortText() = property.name
+ override fun getHtml(formatter: HtmlFormatter) = name
+ override fun getElementHandle() = null
+ override fun getKind() = ElementKind.PROPERTY
+ override fun getModifiers() = emptySet<Modifier>()
+ override fun isLeaf() = isLeaf
+ override fun getNestedItems() = emptyList<StructureItem>()
+ override fun getPosition() = property.textRange.startOffset.toLong()
+ override fun getEndPosition() = property.textRange.endOffset.toLong()
+ override fun getCustomIcon() = ImageIcon(ImageUtilities.loadImage("org/jetbrains/kotlin/completionIcons/field.png"))
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinStructureScanner.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinStructureScanner.kt
new file mode 100644
index 0000000..3f2b890
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/structurescanner/KotlinStructureScanner.kt
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.structurescanner
+
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.csl.api.StructureItem
+import org.netbeans.modules.csl.api.StructureScanner
+import org.netbeans.modules.csl.spi.ParserResult
+import org.openide.filesystems.FileObject
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParserResult
+import org.netbeans.modules.csl.api.StructureScanner.Configuration
+
+class KotlinStructureScanner : StructureScanner {
+
+ override fun getConfiguration() = Configuration(true, true)
+
+ override fun scan(info: ParserResult): List<StructureItem> {
+ val file = info.snapshot.source.fileObject ?: return emptyList()
+ val context = (info as KotlinParserResult).analysisResult?.analysisResult?.bindingContext ?: return emptyList()
+
+ return structureItems(file, context)
+ }
+
+ override fun folds(info: ParserResult): Map<String, List<OffsetRange>> {
+ val file = info.snapshot.source.fileObject ?: return emptyMap()
+
+ return foldMap(file)
+ }
+
+ fun structureItems(file: FileObject, context: BindingContext): List<StructureItem> {
+ if (ProjectUtils.getKotlinProjectForFileObject(file) == null) return emptyList()
+
+ val ktFile = ProjectUtils.getKtFile(file) ?: return emptyList()
+
+ return ktFile.declarations.mapNotNull {
+ when(it) {
+ is KtClassOrObject -> KotlinClassStructureItem(it, false, context)
+ is KtNamedFunction -> KotlinFunctionStructureItem(it, false, context)
+ is KtProperty -> KotlinPropertyStructureItem(it, false, context)
+ else -> null
+ }
+ }
+ }
+
+ fun foldMap(file: FileObject): Map<String, List<OffsetRange>> {
+ if (ProjectUtils.getKotlinProjectForFileObject(file) == null) return emptyMap()
+ val ktFile = ProjectUtils.getKtFile(file) ?: return emptyMap()
+
+ return KotlinFoldingVisitor(ktFile).computeFolds()
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinClasspath.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinClasspath.kt
new file mode 100644
index 0000000..ab0b4b4
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinClasspath.kt
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.utils
+
+object KotlinClasspath {
+
+ private val LIB_RUNTIME_NAME = "kotlin-runtime.jar"
+
+ val kotlinBootClasspath = "${ProjectUtils.KT_HOME}lib\\$LIB_RUNTIME_NAME"
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinImageProvider.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinImageProvider.kt
new file mode 100644
index 0000000..dbc8c18
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinImageProvider.kt
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.utils
+
+import javax.swing.ImageIcon
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.ClassKind
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.VariableDescriptor
+import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
+import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
+import org.openide.util.ImageUtilities
+
+object KotlinImageProvider {
+
+ private val imagesLocation = "org/jetbrains/kotlin/completionIcons/"
+
+ val typeImage = ImageIcon(ImageUtilities.loadImage("${imagesLocation}class.png"))
+ val functionImage = ImageIcon(ImageUtilities.loadImage("${imagesLocation}method.png"))
+
+ private fun getImageIcon(name: String) = ImageIcon(ImageUtilities.loadImage("$imagesLocation$name"))
+
+ fun getImage(descriptor: DeclarationDescriptor?) = when (descriptor) {
+ is ClassDescriptor -> {
+ when (descriptor.kind) {
+ ClassKind.ANNOTATION_CLASS -> getImageIcon("annotation.png")
+ ClassKind.ENUM_CLASS -> getImageIcon("enum.png")
+ ClassKind.INTERFACE -> getImageIcon("interface.png")
+ else -> getImageIcon("class.png")
+ }
+ }
+ is FunctionDescriptor -> getImageIcon("method.png")
+ is VariableDescriptor -> getImageIcon("field.png")
+ is PackageFragmentDescriptor, is PackageViewDescriptor -> getImageIcon("package.png")
+ else -> null
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinMockProject.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinMockProject.kt
new file mode 100644
index 0000000..eba09e9
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/KotlinMockProject.kt
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.utils
+
+import java.io.IOException
+import org.netbeans.api.project.Project
+import org.netbeans.api.project.ProjectManager
+import org.netbeans.spi.project.support.ant.AntProjectHelper
+import org.netbeans.spi.project.support.ant.ProjectGenerator
+import org.openide.filesystems.FileUtil
+import org.openide.modules.Places
+
+object KotlinMockProject {
+
+ private var project: Project? = null
+
+ private fun createHelper(): AntProjectHelper? {
+ val userDirectory = FileUtil.toFileObject(Places.getUserDirectory())
+ val projectName = "ktFilesWithoutProject"
+
+ if (userDirectory.getFileObject(projectName) == null) {
+ try {
+ userDirectory.createFolder(projectName)
+ } catch (ex: IOException) {
+ return null
+ }
+ }
+ return ProjectGenerator.createProject(userDirectory, "org.netbeans.modules.java.j2seproject")
+ }
+
+ fun getMockProject(): Project? {
+ if (project == null) {
+ try {
+ val helper = createHelper() ?: return null
+ project = ProjectManager.getDefault().findProject(helper.projectDirectory)
+ } catch (ex: IOException) {}
+ }
+
+ return project
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/LineEndUtil.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/LineEndUtil.java
new file mode 100644
index 0000000..eeae4aa
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/LineEndUtil.java
@@ -0,0 +1,77 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package org.jetbrains.kotlin.utils;
+
+public class LineEndUtil {
+
+ public static final char CARRIAGE_RETURN_CHAR = '\r';
+ public static final String CARRIAGE_RETURN_STRING = Character.toString(CARRIAGE_RETURN_CHAR);
+ public static final char NEW_LINE_CHAR = '\n';
+ public static final String NEW_LINE_STRING = Character.toString(NEW_LINE_CHAR);
+
+ public static int convertLfToDocumentOffset(String lfText, int offset) {
+ return offset + offsetToLineNumber(lfText, offset);
+ }
+
+ public static int convertCrToDocumentOffset(String crText, int crOffset) {
+ return crOffset - countCrToLineNumber(crText, crOffset);
+ }
+
+ public static int countCrToLineNumber(String lfText, int offset) {
+ int countCR = 0;
+ int curOffset = 0;
+
+ while (curOffset < offset) {
+ if (curOffset == lfText.length()) {
+ break;
+ }
+
+ char c = lfText.charAt(curOffset);
+ if (c == '\r') {
+ countCR++;
+ }
+
+ curOffset++;
+ }
+
+ return countCR;
+ }
+
+ private static int offsetToLineNumber(String lfText, int offset) {
+ int line = 0;
+ int curOffset = 0;
+
+ while (curOffset < offset) {
+ if (curOffset == lfText.length()) {
+ break;
+ }
+
+ char c = lfText.charAt(curOffset);
+ if (c == NEW_LINE_CHAR) {
+ line++;
+ } else if (c == CARRIAGE_RETURN_CHAR) {
+ throw new IllegalArgumentException("Given text shouldn't contain \\r char");
+ }
+
+ curOffset++;
+ }
+
+ return line;
+ }
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/ProjectUtils.java b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/ProjectUtils.java
new file mode 100644
index 0000000..933ad58
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/ProjectUtils.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.utils;
+
+import com.google.common.collect.Sets;
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import javax.swing.text.Document;
+import javax.swing.text.StyledDocument;
+import org.jetbrains.kotlin.builder.KotlinPsiManager;
+import org.jetbrains.kotlin.bundledcompiler.BundledCompiler;
+import org.jetbrains.kotlin.projectsextensions.KotlinProjectHelper;
+import org.jetbrains.kotlin.projectsextensions.ClassPathExtender;
+import org.jetbrains.kotlin.projectsextensions.maven.MavenHelper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.kotlin.log.KotlinLogger;
+import org.jetbrains.kotlin.psi.KtFile;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ui.OpenProjects;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectNotFoundException;
+import org.openide.modules.Places;
+import org.openide.util.Exceptions;
+
+public class ProjectUtils {
+
+ private static final String LIB_FOLDER = "lib";
+ private static final String LIB_EXTENSION = "jar";
+ public static final String FILE_SEPARATOR = System.getProperty("file.separator");
+ public static String KT_HOME;
+
+ static {
+ if (System.getenv("KOTLIN_HOME") != null) {
+ KT_HOME = System.getenv("KOTLIN_HOME") + FILE_SEPARATOR;
+ } else if (System.getenv("KT_HOME") != null) {
+ KT_HOME = System.getenv("KT_HOME") + FILE_SEPARATOR;
+ }
+ }
+
+ public static void checkKtHome() throws IOException {
+ if (KT_HOME == null){
+ File userDirectory = Places.getUserDirectory();
+ if (userDirectory == null) {
+ KotlinLogger.INSTANCE.logWarning("KT_HOME is null!");
+ return;
+ }
+
+ FileObject dir = FileUtil.toFileObject(userDirectory);
+ if (dir == null || dir.getFileObject("kotlinc") == null){
+ KotlinLogger.INSTANCE.logInfo("No kotlinc folder. Adding bundled compiler.");
+ BundledCompiler.getKotlinc();
+ } else {
+ FileObject kotlincDir = dir.getFileObject("kotlinc");
+ FileObject build = kotlincDir.getFileObject("build.txt");
+ if (build == null || !build.asText().equals(BundledCompiler.KOTLIN_VERSION)) {
+ BundledCompiler.getKotlinc();
+ KotlinLogger.INSTANCE.logInfo("New version of bundled compiler");
+ }
+ }
+ KT_HOME = userDirectory.getAbsolutePath() + FILE_SEPARATOR + "kotlinc"
+ + FILE_SEPARATOR;
+ }
+ }
+
+ private static Set<String> createListOfClassPaths(ClassPath boot, ClassPath src, ClassPath compile) {
+ Set<String> classpath = Sets.newHashSet();
+
+ for (ClassPath.Entry entry : boot.entries()){
+ String path = entry.getURL().getFile();
+ if (path != null){
+ try {
+ classpath.add(URLDecoder.decode(path, "UTF-8"));
+ } catch (UnsupportedEncodingException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+
+ for (ClassPath.Entry entry : src.entries()){
+ String path = entry.getURL().getPath();
+ if (path != null){
+ try {
+ classpath.add(URLDecoder.decode(path, "UTF-8"));
+ } catch (UnsupportedEncodingException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+
+ for (ClassPath.Entry entry : compile.entries()){
+ String path = entry.getURL().getPath();
+
+ FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(new File(path)));
+ if (fo != null && fo.isFolder()) continue;
+
+ if (path != null){
+ try {
+ classpath.add(URLDecoder.decode(path, "UTF-8"));
+ } catch (UnsupportedEncodingException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+
+ return classpath;
+ }
+
+ private static Set<String> getProjectClassPath(Project project) {
+ ClassPathExtender extendedProvider = KotlinProjectHelper.INSTANCE.getExtendedClassPath(project);
+ ClassPath boot = extendedProvider.getProjectSourcesClassPath(ClassPath.BOOT);
+ ClassPath src = extendedProvider.getProjectSourcesClassPath(ClassPath.SOURCE);
+ ClassPath compile = extendedProvider.getProjectSourcesClassPath(ClassPath.COMPILE);
+
+ return createListOfClassPaths(boot, src, compile);
+ }
+
+ @NotNull
+ public static Set<String> getClasspath(Project project) {
+ if (KotlinProjectHelper.INSTANCE.checkProject(project)) {
+ return getProjectClassPath(project);
+ }
+
+ return Collections.emptySet();
+ }
+
+ public static String buildLibPath(String libName) {
+ return KT_HOME + buildLibName(libName);
+ }
+
+ private static String buildLibName(String libName) {
+ return LIB_FOLDER + FILE_SEPARATOR + libName + "." + LIB_EXTENSION;
+ }
+
+ public static KtFile getKtFile(FileObject file){
+ return KotlinPsiManager.INSTANCE.getParsedFile(file);
+ }
+
+ public static KtFile getKtFile(String code, FileObject file){
+ return KotlinPsiManager.INSTANCE.parseTextForDiagnostic(code, file);
+ }
+
+ @NotNull
+ public static List<KtFile> getSourceFiles(@NotNull Project project){
+ List<KtFile> ktFiles = new ArrayList<>();
+
+ for (FileObject file : KotlinPsiManager.INSTANCE.getFilesByProject(project, true)){
+ ktFiles.add(getKtFile(file));
+
+ }
+
+ return ktFiles;
+ }
+
+ @NotNull
+ public static List<KtFile> getSourceFilesWithDependencies(@NotNull Project project){
+ List<KtFile> depFiles = new ArrayList<>();
+ if (project.getClass().getName().
+ equals("org.netbeans.modules.maven.NbMavenProjectImpl")) {
+ List<? extends Project> depProjects = MavenHelper.getDependencyProjects(project);
+ for (Project depProject : depProjects) {
+ for (FileObject file : KotlinPsiManager.INSTANCE.getFilesByProject(depProject, false)){
+ depFiles.add(getKtFile(file));
+ }
+ }
+ }
+ List<KtFile> files = getSourceFiles(project);
+ files.addAll(depFiles);
+
+ return files;
+ }
+
+ public static Project getKotlinProjectForFileObject(FileObject file) {
+ return FileOwnerQuery.getOwner(file);
+ }
+
+ public static FileObject getFileObjectForDocument(Document doc) {
+ if (doc == null) {
+ return null;
+ }
+ Object sdp = doc.getProperty(Document.StreamDescriptionProperty);
+
+ if (sdp instanceof FileObject) {
+ return (FileObject) sdp;
+ }
+
+ if (sdp instanceof DataObject) {
+ DataObject dobj = (DataObject) sdp;
+ return dobj.getPrimaryFile();
+ }
+
+ return null;
+ }
+
+ public static DataObject getDataObjectFromFileObject(FileObject file) {
+ DataObject dataObject = null;
+ try {
+ dataObject = DataObject.find(file);
+ } catch (DataObjectNotFoundException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+
+ return dataObject;
+ }
+
+ public static StyledDocument getDocumentFromFileObject(FileObject file) throws IOException{
+ DataObject dataObject = null;
+ try {
+ dataObject = DataObject.find(file);
+ } catch (DataObjectNotFoundException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ if (dataObject == null){
+ return null;
+ }
+
+ EditorCookie editorCookie = (EditorCookie) dataObject.getLookup().lookup(EditorCookie.class);
+ if (editorCookie == null){
+ return null;
+ }
+
+ editorCookie.open();
+ return editorCookie.openDocument();
+ }
+
+ public static Project getValidProject() {
+ for (Project project : OpenProjects.getDefault().getOpenProjects()) {
+ if (KotlinProjectHelper.INSTANCE.checkProject(project)) {
+ return project;
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/findMain.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/findMain.kt
new file mode 100644
index 0000000..39c7475
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/findMain.kt
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.utils
+
+import java.io.File
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
+
+fun KtFile.mainClassName(simple: Boolean = false) = declarations.findMainFunction()
+ ?.let {
+ NoResolveFileClassesProvider.getFileClassInfo(this).facadeClassFqName.let {
+ if (simple) it.shortName().asString() else it.asString()
+ }
+ }
+
+fun KtFile.hasMain() = declarations.findMainFunction() != null
+
+private fun KtNamedFunction.isMain(): Boolean {
+ if (name == "main" && valueParameters.size == 1) {
+ val reference = valueParameters.first().typeReference ?: return false
+
+ return reference.text == "Array<String>"
+ }
+
+ return false
+}
+
+private fun Collection<KtDeclaration>.findMainFunction() =
+ filterIsInstance(KtNamedFunction::class.java).firstOrNull { it.isMain() }
+
+
+
diff --git a/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/importUtils.kt b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/importUtils.kt
new file mode 100644
index 0000000..af4e579
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/jetbrains/kotlin/utils/importUtils.kt
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.jetbrains.kotlin.utils
+
+import org.jetbrains.kotlin.idea.util.ImportInsertHelper
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.idea.util.ImportDescriptorResult
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.resolve.ImportPath
+import java.util.Comparator
+import org.jetbrains.kotlin.idea.imports.ImportPathComparator
+import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
+
+class KotlinImportInserterHelper : ImportInsertHelper() {
+ override val importSortComparator: Comparator<ImportPath> = ImportPathComparator
+
+ override fun importDescriptor(file: KtFile, descriptor: DeclarationDescriptor, forceAllUnderImport: Boolean): ImportDescriptorResult {
+ throw UnsupportedOperationException()
+ }
+
+ override fun isImportedWithDefault(importPath: ImportPath, contextFile: KtFile): Boolean {
+ val defaultImports = JvmPlatform.getDefaultImports(LanguageVersionSettingsImpl.DEFAULT)
+ return importPath.isImported(defaultImports)
+ }
+
+ override fun mayImportOnShortenReferences(descriptor: DeclarationDescriptor) = false
+}
+
+fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean = when {
+ skipAliasedImports && importPath.hasAlias() -> false
+ importPath.isAllUnder && !isRoot -> importPath.fqnPart() == this.parent()
+ else -> importPath.fqnPart() == this
+}
+
+fun ImportPath.isImported(alreadyImported: ImportPath): Boolean =
+ if (isAllUnder || hasAlias()) this == alreadyImported else fqnPart().isImported(alreadyImported)
+
+fun ImportPath.isImported(imports: Iterable<ImportPath>): Boolean = imports.any { isImported(it) }
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/java/org/netbeans/modules/maven/kotlin/KotlinActionProvider.java b/contrib/kotlin/src/main/java/org/netbeans/modules/maven/kotlin/KotlinActionProvider.java
new file mode 100644
index 0000000..a89e2a8
--- /dev/null
+++ b/contrib/kotlin/src/main/java/org/netbeans/modules/maven/kotlin/KotlinActionProvider.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package org.netbeans.modules.maven.kotlin;
+
+import java.util.Map;
+import org.jetbrains.kotlin.projectsextensions.maven.UtilsKt;
+import org.netbeans.modules.maven.spi.actions.ActionConvertor;
+import org.netbeans.modules.maven.spi.actions.ReplaceTokenProvider;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.util.Lookup;
+
+@ProjectServiceProvider(service={ReplaceTokenProvider.class, ActionConvertor.class},
+ projectType={"org-netbeans-modules-maven"})
+public class KotlinActionProvider implements ReplaceTokenProvider, ActionConvertor {
+
+ @Override
+ public Map<String, String> createReplacements(String action, Lookup lookup) {
+ return UtilsKt.createReplacements(action, lookup);
+ }
+
+ @Override
+ public String convert(String action, Lookup lookup) {
+ return UtilsKt.convert(action, lookup);
+ }
+
+}
diff --git a/contrib/kotlin/src/main/nbm/manifest.mf b/contrib/kotlin/src/main/nbm/manifest.mf
new file mode 100644
index 0000000..dd3d34b
--- /dev/null
+++ b/contrib/kotlin/src/main/nbm/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module-Install: org/jetbrains/kotlin/installer/KotlinInstaller.class
+OpenIDE-Module-Layer: org/jetbrains/kotlin/layer.xml
+OpenIDE-Module-Localizing-Bundle: org/jetbrains/kotlin/Bundle.properties
+OpenIDE-Module-Needs: javax.script.ScriptEngine.freemarker
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/Bundle.properties b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/Bundle.properties
new file mode 100644
index 0000000..ccfb65e
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/Bundle.properties
@@ -0,0 +1,18 @@
+#Localized module labels. Defaults taken from POM (<name>, <description>, <groupId>) if unset.
+#OpenIDE-Module-Name=
+#OpenIDE-Module-Short-Description=
+#OpenIDE-Module-Long-Description=
+#OpenIDE-Module-Display-Category=
+#Mon Sep 21 20:40:16 MSK 2015
+
+#OpenIDE-Module-Name=AntProjectFactorySample
+#Templates/Project/Samples/DemoProject.zip=Demo
+
+QuickSearch/Navigate/org-jetbrains-kotlin-search-GoToKotlinTypeProvider.instance=Navigate
+text/x-kt=Kotlin
+identifier=Identifier
+keyword=Keyword
+comment=Comment
+string=String
+whitespace=Whitespace
+annotation=Annotation
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/FontAndColors.xml b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/FontAndColors.xml
new file mode 100644
index 0000000..80e036b
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/FontAndColors.xml
@@ -0,0 +1,43 @@
+<!DOCTYPE fontscolors PUBLIC
+ "-//NetBeans//DTD Editor Fonts and Colors settings 1.1//EN"
+ "https://netbeans.org/dtds/EditorFontsColors-1_1.dtd">
+<fontscolors>
+ <fontcolor name="IDENTIFIER" default="identifier"/>
+ <fontcolor name="KEYWORD" default="keyword" foreColor="blue">
+ <font style="bold"/>
+ </fontcolor>
+ <fontcolor name="SINGLE_LINE_COMMENT" default="comment"/>
+ <fontcolor name="MULTI_LINE_COMMENT" default="comment"/>
+ <fontcolor name="STRING" default="string"/>
+ <fontcolor name="WHITESPACE" default="whitespace"/>
+ <fontcolor name="ANNOTATION" default="annotation" foreColor="red"/>
+ <fontcolor name="KDOC_TAG_NAME" default="comment" underline="gray">
+ <font style="bold, italic"/>
+ </fontcolor>
+ <fontcolor name="KDOC_LINK" default="comment" underline="black">
+ <font style="bold, italic"/>
+ </fontcolor>
+
+ <!--"semantic" highlighting:-->
+ <fontcolor name="mod-field" default="field"/>
+ <fontcolor name="mod-local-variable"/>
+ <fontcolor name="mod-parameter"/>
+ <fontcolor name="mod-static" >
+ <font style="bold+italic" />
+ </fontcolor>
+ <fontcolor name="mod-type-parameter-use" foreColor="20999D" />
+ <fontcolor name="mod-annotation-type" foreColor="blue"/>
+ <fontcolor name="mod-enum">
+ <font style="bold" />
+ </fontcolor>
+ <fontcolor name="mod-interface"/>
+ <fontcolor name="mod-class" default="class"/>
+ <fontcolor name="mod-declaration">
+ <font style="bold" />
+ </fontcolor>
+ <fontcolor name="mod-deprecated" strikeThrough="404040" />
+ <fontcolor name="mark-occurrences" bgColor="ECEBA3"/>
+ <fontcolor name="mod-custom1" bgColor="CCFFCC"/>
+ <fontcolor name="mod-custom2" underline="black"/>
+
+</fontscolors>
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/KtTemplate.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/KtTemplate.kt
new file mode 100644
index 0000000..792d467
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/KtTemplate.kt
@@ -0,0 +1,48 @@
+/* Block comment */
+package hello
+import kotlin.util.* // line comment
+
+/**
+ * Doc comment here for `SomeClass`
+ * @see Iterator#next()
+ */
+@Deprecated("Deprecated class")
+public class MyClass<out T : Iterable<T>>(var prop1 : Int)
+ fun foo(nullable : String?, r : Runnable, f : () -> Int, fl : FunctionLike, dyn: dynamic) {
+ println("length\nis ${nullable?.length} \e")
+ val ints = java.util.ArrayList<Int?>(2)
+ ints[0] = 102 + f() + fl()
+ val myFun = { -> "" };
+ var ref = ints.size()
+ if (!ints.empty) {
+ ints.forEach lit@ {
+ if (it == null) return@lit
+ println(it + ref)
+ }
+ }
+ dyn.dynamicCall()
+ dyn.dynamicProp = 5
+ }
+}
+
+fun Int?.bar() {
+ if (this != null) {
+ println(toString())
+ }
+ else {
+ println(this.toString())
+ }
+}
+
+var globalCounter : Int = 5
+ get() {
+ return field
+ }
+
+public abstract class Abstract {
+}
+
+object Obj
+
+enum class E { A }
+ Bad character: \n
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/annotation.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/annotation.png
new file mode 100644
index 0000000..52ff9d6
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/annotation.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/class.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/class.png
new file mode 100644
index 0000000..220e6f3
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/class.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/constructor.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/constructor.png
new file mode 100644
index 0000000..fd95f9d
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/constructor.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/enum.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/enum.png
new file mode 100644
index 0000000..f54c89b
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/enum.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field.png
new file mode 100644
index 0000000..06a86fb
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_package_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_package_private.png
new file mode 100644
index 0000000..5cace13
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_package_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_private.png
new file mode 100644
index 0000000..1d0ee3e
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_protected.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_protected.png
new file mode 100644
index 0000000..589610c
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_protected.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static.png
new file mode 100644
index 0000000..3239478
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static_package_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static_package_private.png
new file mode 100644
index 0000000..c808784
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static_package_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static_private.png
new file mode 100644
index 0000000..3b1c00a
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/field_static_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/interface.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/interface.png
new file mode 100644
index 0000000..ae582f7
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/interface.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/localVariable.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/localVariable.png
new file mode 100644
index 0000000..50971fb
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/localVariable.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method.png
new file mode 100644
index 0000000..7be8a37
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_package_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_package_private.png
new file mode 100644
index 0000000..d4da75f
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_package_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_private.png
new file mode 100644
index 0000000..5bbdd17
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_protected.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_protected.png
new file mode 100644
index 0000000..325ed18
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_protected.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static.png
new file mode 100644
index 0000000..414e584
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_package_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_package_private.png
new file mode 100644
index 0000000..694eb07
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_package_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_private.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_private.png
new file mode 100644
index 0000000..0a5e4b1
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_private.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_protected.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_protected.png
new file mode 100644
index 0000000..e5f9c9b
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/method_static_protected.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/package.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/package.png
new file mode 100644
index 0000000..69da74d
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/completionIcons/package.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/debugger/Bundle.properties b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/debugger/Bundle.properties
new file mode 100644
index 0000000..8e383f7
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/debugger/Bundle.properties
@@ -0,0 +1,60 @@
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
+#
+# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+# Other names may be trademarks of their respective owners.
+#
+# The contents of this file are subject to the terms of either the GNU
+# General Public License Version 2 only ("GPL") or the Common
+# Development and Distribution License("CDDL") (collectively, the
+# "License"). You may not use this file except in compliance with the
+# License. You can obtain a copy of the License at
+# http://www.netbeans.org/cddl-gplv2.html
+# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+# specific language governing permissions and limitations under the
+# License. When distributing the software, include this License Header
+# Notice in each file and include the License file at
+# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the GPL Version 2 section of the License file that
+# accompanied this code. If applicable, add the following below the
+# License Header, with the fields enclosed by brackets [] replaced by
+# your own identifying information:
+# "Portions Copyrighted [year] [name of copyright owner]"
+#
+# Contributor(s):
+#
+# The Original Software is NetBeans. The Initial Developer of the Original
+# Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
+# Microsystems, Inc. All Rights Reserved.
+#
+# If you wish your version of this file to be governed by only the CDDL
+# or only the GPL Version 2, indicate your decision by adding
+# "[Contributor] elects to include this software in this distribution
+# under the [CDDL or GPL Version 2] license." If you do not indicate a
+# single choice of license, a recipient has the option to distribute
+# your version of this file under either the CDDL, the GPL Version 2 or
+# to extend the choice of license to its licensees as provided above.
+# However, if you add GPL Version 2 code and therefore, elected the GPL
+# Version 2 license, then the option applies only if the new code is
+# made subject to such option by the copyright holder.
+
+#manifest's description entries
+OpenIDE-Module-Name=JPDA Debugger API
+OpenIDE-Module-Display-Category=Debugging
+OpenIDE-Module-Short-Description=JPDA Debugger API
+OpenIDE-Module-Long-Description=JPDA Debugger API
+OpenIDE-Module-Package-Dependency-Message=\
+ <b>The JDK is missing and is required to run some NetBeans modules</b><br> \
+ Please use the --jdkhome command line option to specify a JDK<br>\
+ installation or see <a href="http://wiki.netbeans.org/FaqRunningOnJre">http://wiki.netbeans.org/FaqRunningOnJre</a> for<br> \
+ more information.
+MSG_NO_DEBUGGER=No debugger engine available.
+
+ClassBrkp_Type=Class Load/Unload
+ExceptionBrkp_Type=Exception
+FieldBrkp_Type=Field
+LineBrkp_Type=Line
+MethodBrkp_Type=Method
+ThreadBrkp_Type=Thread
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/KotlinFileDescription.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/KotlinFileDescription.html
new file mode 100644
index 0000000..f840bd9
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/KotlinFileDescription.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Creates a new Kotlin file.
+ </body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/KtTemplate.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/KtTemplate.kt
new file mode 100644
index 0000000..5cc4373
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/KtTemplate.kt
@@ -0,0 +1,10 @@
+<#if package?? && package != "">
+package ${package}
+
+</#if>
+/**
+*
+* @author ${user}
+* Created on ${date}
+*/
+
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/content.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/content.kt
new file mode 100644
index 0000000..5cc4373
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/content.kt
@@ -0,0 +1,10 @@
+<#if package?? && package != "">
+package ${package}
+
+</#if>
+/**
+*
+* @author ${user}
+* Created on ${date}
+*/
+
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/content.kt.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/content.kt.template
new file mode 100644
index 0000000..b21ff18
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/content.kt.template
@@ -0,0 +1,14 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package}
+
+</#if>
+/*
+
+ @author ${user}
+ Created on ${date}
+*/
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/class.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/class.kt
new file mode 100644
index 0000000..b7f7c7a
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/class.kt
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+<#if package?? && package != "">
+package ${package}
+</#if>
+/*
+
+ @author ${user}
+ Created on ${date}
+*/
+
+class ${name} {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/content.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/content.kt
new file mode 100644
index 0000000..0af6ceb
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/content.kt
@@ -0,0 +1,12 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+<#if package?? && package != "">
+package ${package}
+</#if>
+/*
+
+ @author ${user}
+ Created on ${date}
+*/
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/enum.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/enum.kt
new file mode 100644
index 0000000..a8c5359
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/enum.kt
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+<#if package?? && package != "">
+package ${package}
+</#if>
+/*
+
+ @author ${user}
+ Created on ${date}
+*/
+
+enum class ${name} {
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/interface.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/interface.kt
new file mode 100644
index 0000000..c9976e6
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/interface.kt
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+<#if package?? && package != "">
+package ${package}
+</#if>
+/*
+
+ @author ${user}
+ Created on ${date}
+*/
+
+interface ${name} {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/kt.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/kt.html
new file mode 100644
index 0000000..f3b66dc
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/kt.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Simple Kotlin file
+ </body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktClass.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktClass.html
new file mode 100644
index 0000000..6443785
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktClass.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Kotlin class
+ </body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktEnum.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktEnum.html
new file mode 100644
index 0000000..68a9fbb
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktEnum.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Creates a new Kotlin enum.
+ </body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktInterface.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktInterface.html
new file mode 100644
index 0000000..2ff798a
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktInterface.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Kotlin interface
+ </body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktObject.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktObject.html
new file mode 100644
index 0000000..7efe648
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/ktObject.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ Kotlin object
+ </body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/object.kt b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/object.kt
new file mode 100644
index 0000000..0d5898c
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/object.kt
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+<#if package?? && package != "">
+package ${package}
+</#if>
+/*
+
+ @author ${user}
+ Created on ${date}
+*/
+
+object ${name} {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/Bundle.properties b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/Bundle.properties
new file mode 100644
index 0000000..d535d2a
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/Bundle.properties
@@ -0,0 +1,118 @@
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
+#
+# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+# Other names may be trademarks of their respective owners.
+#
+# The contents of this file are subject to the terms of either the GNU
+# General Public License Version 2 only ("GPL") or the Common
+# Development and Distribution License("CDDL") (collectively, the
+# "License"). You may not use this file except in compliance with the
+# License. You can obtain a copy of the License at
+# http://www.netbeans.org/cddl-gplv2.html
+# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+# specific language governing permissions and limitations under the
+# License. When distributing the software, include this License Header
+# Notice in each file and include the License file at
+# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the GPL Version 2 section of the License file that
+# accompanied this code. If applicable, add the following below the
+# License Header, with the fields enclosed by brackets [] replaced by
+# your own identifying information:
+# "Portions Copyrighted [year] [name of copyright owner]"
+#
+# Contributor(s):
+#
+# The Original Software is NetBeans. The Initial Developer of the Original
+# Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+# Microsystems, Inc. All Rights Reserved.
+#
+# If you wish your version of this file to be governed by only the CDDL
+# or only the GPL Version 2, indicate your decision by adding
+# "[Contributor] elects to include this software in this distribution
+# under the [CDDL or GPL Version 2] license." If you do not indicate a
+# single choice of license, a recipient has the option to distribute
+# your version of this file under either the CDDL, the GPL Version 2 or
+# to extend the choice of license to its licensees as provided above.
+# However, if you add GPL Version 2 code and therefore, elected the GPL
+# Version 2 license, then the option applies only if the new code is
+# made subject to such option by the copyright holder.
+
+OpenIDE-Module-Name=Java Project Support UI
+OpenIDE-Module-Display-Category=Java
+OpenIDE-Module-Short-Description=Support for defining Ant-based project types involving Java sources.
+OpenIDE-Module-Long-Description=\
+ Helper APIs which provide common infrastructure needed for creating project \
+ types which work with Java sources. Supplies the package view, package chooser \
+ for the New File wizard, etc.
+
+Templates/Classes=Java
+
+# JavaTargetChooserPanelGUI
+LBL_JavaTargetChooserPanelGUI_Name=Name and Location
+LBL_JavaTargetChooserPanelGUI_jLabel1=&Location\:
+LBL_JavaTargetChooserPanelGUI_jLabel2=Pac&kage\:
+LBL_JavaTargetChooserPanelGUI_ClassName_Label=Class &Name\:
+LBL_JavaTargetChooserPanelGUI_PackageName_Label=Package &Name\:
+LBL_JavaTargetChooserPanelGUI_PackageName_PleaseWait=Please Wait...
+LBL_JavaTargetChooserPanelGUI_CreatedFile_Label=&Created File\:
+LBL_JavaTargetChooserPanelGUI_CreatedFolder_Label=&Created Folder\:
+LBL_JavaTargetChooserPanelGUI_jLabel5=&Project\:
+
+LBL_JavaTargetChooserPanelGUI_DefaultNewPackageName=newpackage
+LBL_JavaTargetChooserPanelGUI_NewJavaClassPrefix=New
+
+ERR_JavaTargetChooser_InvalidPackage=The Package Name is not valid
+ERR_JavaTargetChooser_InvalidClass=The Class Name is not valid
+ERR_JavaTargetChooser_DefaultPackage=Warning: It is highly recommended that you do not place Java classes in the default package.
+ERR_JavaTargetChooser_InvalidFolder=The Package is not a folder
+
+INFO_JavaTargetChooser_ProvideClassName=Provide valid Java Class name
+INFO_JavaTargetChooser_ProvidePackageName=Provide valid Java Package name
+
+# copied from project/ui/Bundle
+MSG_fs_or_folder_does_not_exist=The target folder does not exist.
+MSG_fs_is_readonly=The target folder is read-only.
+# {0} - name of the existing file
+MSG_file_already_exist=The file {0} already exists.
+
+
+AD_JavaTargetChooserPanelGUI=N/A
+
+AD_documentNameTextField=N/A
+
+AD_projectTextField=N/A
+
+AD_rootComboBox=N/A
+
+AD_packageComboBox=N/A
+
+AD_fileTextField=N/A
+
+# PackageDisplayUtils
+LBL_DefaultPackage=<default package>
+# {0} - full package name
+LBL_package= Java Source Package ({0})
+# {0} - full package name
+LBL_public_package=Exported Java Source Package ({0})
+# {0} - full package name
+LBL_private_package=Private Java Source Package ({0})
+
+
+ERR_JavaTargetChooser_CantUseDefaultPackage=Provide a package name.
+FixProjectSourceLevel.jLabel2.text=The project source/binary format requires a newer java platform ({0}).
+LBL_FixProfile_BrokenLibs=&The following project libraries have invalid profile:
+LBL_FixProfile_remove=&Remove
+TIP_FixProfile_Remove=Remove library from project
+LBL_FixProfile_changeProfile=Change &Project Profile To:
+AD_FixProfile_BrokenLibs=The libraries with higher or invalid value of JRE profile.
+AD_FixProfile_changeProfile=Update project profile.
+AN_FixProfile_Profiles=Profiles
+AD_FixProfile_Profiles=Profiles
+FixProfile.jLabel1.AccessibleContext.accessibleName=&The following project libraries have invalid value of profile:
+FixProjectSourceLevel.managePlatforms.text=&Manage Platforms...
+FixProjectSourceLevel.downgradeLevel.text=&Downgrade Project Source/Binary Format to {0}
+FixProjectSourceLevel.useOtherPlatform.text=Use Other Java &Platform
+FixProjectSourceLevel.jLabel1.text=&Java Platform:
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/AnnotationType.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/AnnotationType.html
new file mode 100644
index 0000000..e054415
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/AnnotationType.html
@@ -0,0 +1,50 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 2005 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new Java annotation type. To be able to use annotation type files,
+your project must use JDK 5.0 or compatible.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/AnnotationType.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/AnnotationType.java.template
new file mode 100644
index 0000000..12f6fc1
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/AnnotationType.java.template
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public @interface ${name} {
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Applet.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Applet.html
new file mode 100644
index 0000000..3d2bc00
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Applet.html
@@ -0,0 +1,52 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new AWT (Abstract Window Toolkit) applet. An applet is a Java class
+that can run in any Java-enabled browser. <b>Note</b>: This template does not contain
+form code that allows you to design the applet visually in the Form Editor.
+For visual design, start with the Applet template under Java GUI Forms | AWT Forms.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Applet.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Applet.java.template
new file mode 100644
index 0000000..d8e28e6
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Applet.java.template
@@ -0,0 +1,27 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+import java.applet.Applet;
+
+/**
+ *
+ * @author ${user}
+ */
+public class ${name} extends Applet {
+
+ /**
+ * Initialization method that will be called after the applet is loaded
+ * into the browser.
+ */
+ public void init() {
+ // TODO start asynchronous download of heavy resources
+ }
+
+ // TODO overwrite start(), stop() and destroy() methods
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Class.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Class.html
new file mode 100644
index 0000000..6112ad5
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Class.html
@@ -0,0 +1,51 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new plain Java class. This template is useful for creating new
+non-visual classes.
+
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Class.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Class.java.template
new file mode 100644
index 0000000..e9890cf
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Class.java.template
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public class ${name} {
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Classes.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Classes.html
new file mode 100644
index 0000000..9fd9c46
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Classes.html
@@ -0,0 +1,51 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+This category has templates for various kinds of Java classes.
+Using these templates allows you to write Java code by hand. To design dialogs
+or Frames visually, use the templates in the Java GUI Forms category.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Empty.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Empty.html
new file mode 100644
index 0000000..d893340
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Empty.html
@@ -0,0 +1,50 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates an empty Java source file. No code is generated except for the required
+package statement. Use this template to create a class from scratch.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Empty.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Empty.java.template
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Empty.java.template
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Enum.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Enum.html
new file mode 100644
index 0000000..089e81c
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Enum.html
@@ -0,0 +1,50 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 2005 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new Java enum file. To be able to use enum files, your project must use
+JDK 5.0 or compatible.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Enum.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Enum.java.template
new file mode 100644
index 0000000..20d8e3d
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Enum.java.template
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public enum ${name} {
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Exception.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Exception.html
new file mode 100644
index 0000000..7316ebc
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Exception.html
@@ -0,0 +1,49 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new subclass of Exception with an optional detailed message.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Exception.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Exception.java.template
new file mode 100644
index 0000000..0c4f294
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Exception.java.template
@@ -0,0 +1,30 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public class ${name} extends Exception {
+
+ /**
+ * Creates a new instance of <code>${name}</code> without detail message.
+ */
+ public ${name}() {
+ }
+
+
+ /**
+ * Constructs an instance of <code>${name}</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ${name}(String msg) {
+ super(msg);
+ }
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Interface.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Interface.html
new file mode 100644
index 0000000..8c055a9
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Interface.html
@@ -0,0 +1,49 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new Java interface.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Interface.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Interface.java.template
new file mode 100644
index 0000000..a830a8b
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Interface.java.template
@@ -0,0 +1,16 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public interface ${name} {
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/JApplet.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/JApplet.html
new file mode 100644
index 0000000..8b02765
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/JApplet.html
@@ -0,0 +1,52 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new JFC (Swing) applet. An applet is a Java class that can run in any
+Java-enabled browser. <b>Note</b>: This template does not contain form code that
+allows you to design the applet visually in the Form Editor. For visual design,
+start with the JApplet template under Java GUI Forms.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/JApplet.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/JApplet.java.template
new file mode 100644
index 0000000..51e5814
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/JApplet.java.template
@@ -0,0 +1,28 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+import javax.swing.JApplet;
+
+/**
+ *
+ * @author ${user}
+ */
+public class ${name} extends JApplet {
+
+ /**
+ * Initialization method that will be called after the applet is loaded
+ * into the browser.
+ */
+ public void init() {
+ // TODO start asynchronous download of heavy resources
+ }
+
+ // TODO overwrite start(), stop() and destroy() methods
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Main.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Main.html
new file mode 100644
index 0000000..abaf9ad
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Main.html
@@ -0,0 +1,52 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new Java class with a <code>main</code> method permitting it to be run as a console
+application. If you want to design a visual application, you might prefer to use
+the JFrame template under Java GUI Forms, or an application skeleton under
+Java GUI Forms | Sample Forms.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Main.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Main.java.template
new file mode 100644
index 0000000..1c29c84
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Main.java.template
@@ -0,0 +1,23 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public class ${name} {
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ // TODO code application logic here
+ }
+
+}
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Package.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Package.html
new file mode 100644
index 0000000..5e7a985
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Package.html
@@ -0,0 +1,50 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a package to hold Java source files. This package physically takes the
+form of an empty folder on your disk.
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Singleton.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Singleton.html
new file mode 100644
index 0000000..b0751ad
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Singleton.html
@@ -0,0 +1,51 @@
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<BODY>
+Creates a new Java singleton class. This template is useful for creating new
+classes allowing single instance.
+
+</BODY></HTML>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Singleton.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Singleton.java.template
new file mode 100644
index 0000000..8438f11
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/Singleton.java.template
@@ -0,0 +1,26 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+
+</#if>
+/**
+ *
+ * @author ${user}
+ */
+public class ${name} {
+
+ private ${name}() {
+ }
+
+ public static ${name} getInstance() {
+ return ${name}Holder.INSTANCE;
+ }
+
+ private static class ${name}Holder {
+ private static final ${name} INSTANCE = new ${name}();
+ }
+ }
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/broken-reference.gif b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/broken-reference.gif
new file mode 100644
index 0000000..c7cc543
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/broken-reference.gif
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/jar.gif b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/jar.gif
new file mode 100644
index 0000000..4d39401
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/jar.gif
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/libraries.gif b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/libraries.gif
new file mode 100644
index 0000000..56d4425
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/libraries.gif
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/main-class.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/main-class.png
new file mode 100644
index 0000000..bd6deb8
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/main-class.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/package-info.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/package-info.html
new file mode 100644
index 0000000..f8dca49
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/package-info.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is NetBeans. The Initial Developer of the Original
+Software is Sun Microsystems, Inc. Portions Copyright 2005 Sun
+Microsystems, Inc. All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+-->
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+</head>
+<body>
+Creates a new Java package-info. To be able to use package annotations,
+your project must use JDK 5.0 or compatible.
+</body>
+</html>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/package-info.java.template b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/package-info.java.template
new file mode 100644
index 0000000..9f18646
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/package-info.java.template
@@ -0,0 +1,8 @@
+<#assign licenseFirst = "/*">
+<#assign licensePrefix = " * ">
+<#assign licenseLast = " */">
+<#include "${project.licensePath}">
+
+<#if package?? && package != "">
+package ${package};
+</#if>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/resolved-reference.gif b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/resolved-reference.gif
new file mode 100644
index 0000000..8d8c7e4
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/file/templates/packagechooser/resources/resolved-reference.gif
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/important_files.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/important_files.png
new file mode 100644
index 0000000..0ddc49b
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/important_files.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kotlin.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kotlin.png
new file mode 100644
index 0000000..022c56d
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kotlin.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kotlinc/kotlinc.zip b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kotlinc/kotlinc.zip
new file mode 100644
index 0000000..d68b044
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kotlinc/kotlinc.zip
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kt.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kt.png
new file mode 100644
index 0000000..cb20967
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/kt.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/layer.xml b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/layer.xml
new file mode 100644
index 0000000..924b796
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/layer.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+<filesystem>
+ <!-- Projects extensions -->
+ <folder name="Projects">
+ <folder name="org-netbeans-modules-java-j2seproject">
+ <folder name="Lookup">
+ <file name="org.jetbrains.kotlin.projectsextensions.j2se.lookup.J2SEProjectLookupProviderExtension.instance"/>
+ </folder>
+ </folder>
+ <folder name="org-netbeans-modules-maven">
+ <folder name="Lookup">
+ <file name="org.jetbrains.kotlin.projectsextensions.maven.lookup.MavenProjectLookupProviderExtension.instance"/>
+ </folder>
+ </folder>
+ <folder name="org.netbeans.gradle.project">
+ <folder name="Lookup">
+ <file name="org.jetbrains.kotlin.projectsextensions.gradle.lookup.GradleProjectLookupProviderExtension.instance"/>
+ </folder>
+ </folder>
+ </folder>
+
+ <folder name="Loaders">
+ <folder name="text">
+ <folder name="x-kt">
+ <folder name="Actions">
+ <file name="RunFile.shadow">
+ <attr name="originalFile" stringvalue="Actions/Project/org-netbeans-modules-project-ui-RunSingle.instance"/>
+ <attr name="position" intvalue="1265"/>
+ </file>
+ <file name="org-netbeans-modules-debugger-ui-actions-DebugFileAction.shadow">
+ <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-DebugFileAction.instance"/>
+ <attr name="position" intvalue="1266"/>
+ </file>
+ <file name="TestFile.shadow">
+ <attr name="originalFile" stringvalue="Actions/Project/org-netbeans-modules-project-ui-TestSingle.instance"/>
+ <attr name="position" intvalue="1267"/>
+ </file>
+ <file name="org-netbeans-modules-debugger-ui-actions-DebugTestFileAction.shadow">
+ <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-DebugTestFileAction.instance"/>
+ <attr name="position" intvalue="1268"/>
+ </file>
+ </folder>
+ <file name="RefactoringAll.instance">
+ <attr name="instanceCreate" methodvalue="org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory.popupSubmenuAction"/>
+ </file>
+ </folder>
+ </folder>
+ </folder>
+
+ <folder name="Editors">
+ <folder name="text">
+ <folder name="x-kt">
+ <attr name="SystemFileSystem.localizingBundle" stringvalue="org.jetbrains.kotlin.Bundle"/>
+ <folder name="FontsColors">
+ <folder name="NetBeans">
+ <folder name="Defaults">
+ <file name="FontAndColors.xml" url="FontAndColors.xml">
+ <attr name="SystemFileSystem.localizingBundle" stringvalue="org.jetbrains.kotlin.Bundle"/>
+ </file>
+ </folder>
+ </folder>
+ </folder>
+ <folder name="GlyphGutterActions">
+ <file name="org-jetbrains-kotlin-debugger-KotlinToggleBreakpointAction.instance">
+ <!--<attr name="originalFile" stringValue="Actions/Debug/org-jetbrains-kotlin-debugger-KotlinToggleBreakpointAction.instance"/>-->
+ <attr name="position" intvalue="2500"/>
+ </file>
+ </folder>
+ <folder name="Popup">
+ <file name="RunFile.shadow">
+ <attr name="originalFile" stringvalue="Actions/Project/org-netbeans-modules-project-ui-RunSingle.instance"/>
+ <attr name="position" intvalue="1790"/>
+ </file>
+ <file name="org-netbeans-modules-debugger-ui-actions-DebugFileAction.shadow">
+ <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-DebugFileAction.instance"/>
+ <attr name="position" intvalue="1791"/>
+ </file>
+ <file name="TestFile.shadow">
+ <attr name="originalFile" stringvalue="Actions/Project/org-netbeans-modules-project-ui-TestSingle.instance"/>
+ <attr name="position" intvalue="1792"/>
+ </file>
+ <file name="org-netbeans-modules-debugger-ui-actions-DebugTestFileAction.shadow">
+ <attr name="originalFile" stringvalue="Actions/Debug/org-netbeans-modules-debugger-ui-actions-DebugTestFileAction.instance"/>
+ <attr name="position" intvalue="1793"/>
+ </file>
+ <file name="RefactoringAll.instance">
+ <attr name="instanceCreate" methodvalue="org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory.editorSubmenuAction"/>
+ <attr name="position" intvalue="1794"/>
+ </file>
+ </folder>
+ <file name="JavaIndexer.shadow">
+ <attr name="originalFile" stringvalue="Editors/text/x-java/JavaIndexer.instance"/>
+ </file>
+ </folder>
+ </folder>
+ </folder>
+
+ <folder name="OptionsDialog">
+ <folder name="PreviewExamples">
+ <folder name="text">
+ <file name="x-kt" url="KtTemplate.kt"/>
+ </folder>
+ </folder>
+ </folder>
+
+ <folder name="QuickSearch">
+ <folder name="GoToKotlinDeclaration">
+ <attr name="command" stringvalue="kt"/>
+ <attr name="position" intvalue="0"/>
+ <file name="org-jetbrains-kotlin-search-GoToKotlinTypeProvider.instance">
+ <attr name="displayName" bundlevalue="org.jetbrains.kotlin.Bundle#QuickSearch/GoToKotlinType/org-jetbrains-kotlin-search-GoToKotlinTypeProvider.instance"/>
+ </file>
+ </folder>
+ </folder>
+
+ <folder name="Debugger">
+ <file name="org-jetbrains-kotlin-debugger-KotlinToggleBreakpointActionProvider.instance">
+ <attr name="serviceName" stringvalue="org.jetbrains.kotlin.debugger.KotlinToggleBreakpointActionProvider"/>
+ <attr name="serviceClass" stringvalue="org.netbeans.spi.debugger.ActionsProvider"/>
+ <attr name="debugger_actions" stringvalue="[toggleBreakpoint]"/>
+ <attr name="debugger_activateForMIMETypes" stringvalue="[text/x-kt]"/>
+ <attr name="instanceOf" stringvalue="org.netbeans.spi.debugger.ActionsProvider"/>
+ <attr methodvalue="org.netbeans.spi.debugger.ActionsProvider$ContextAware.createService" name="instanceCreate"/>
+ </file>
+
+ <folder name="netbeans-JPDASession">
+ <file name="org-jetbrains-kotlin-debugger-KotlinSourcePathProvider.instance">
+ <attr name="serviceName" stringvalue="org.jetbrains.kotlin.debugger.KotlinSourcePathProvider"/>
+ <attr name="serviceClass" stringvalue="org.netbeans.spi.debugger.jpda.SourcePathProvider"/>
+ <attr name="instanceOf" stringvalue="org.netbeans.spi.debugger.jpda.SourcePathProvider"/>
+ <attr methodvalue="org.netbeans.spi.debugger.jpda.SourcePathProvider$ContextAware.createService" name="instanceCreate"/>
+ </file>
+ </folder>
+
+ </folder>
+
+</filesystem>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/lib.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/lib.png
new file mode 100644
index 0000000..40c6951
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/lib.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/Bundle.properties b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/Bundle.properties
new file mode 100644
index 0000000..1e05e30
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/Bundle.properties
@@ -0,0 +1,56 @@
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
+#
+# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+# Other names may be trademarks of their respective owners.
+#
+# The contents of this file are subject to the terms of either the GNU
+# General Public License Version 2 only ("GPL") or the Common
+# Development and Distribution License("CDDL") (collectively, the
+# "License"). You may not use this file except in compliance with the
+# License. You can obtain a copy of the License at
+# http://www.netbeans.org/cddl-gplv2.html
+# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+# specific language governing permissions and limitations under the
+# License. When distributing the software, include this License Header
+# Notice in each file and include the License file at
+# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the GPL Version 2 section of the License file that
+# accompanied this code. If applicable, add the following below the
+# License Header, with the fields enclosed by brackets [] replaced by
+# your own identifying information:
+# "Portions Copyrighted [year] [name of copyright owner]"
+#
+# Contributor(s):
+#
+# The Original Software is the Accelerators module.
+# The Initial Developer of the Original Software is Andrei Badea.
+# Portions Copyright 2005-2006 Andrei Badea.
+# All Rights Reserved.
+#
+# If you wish your version of this file to be governed by only the CDDL
+# or only the GPL Version 2, indicate your decision by adding
+# "[Contributor] elects to include this software in this distribution
+# under the [CDDL or GPL Version 2] license." If you do not indicate a
+# single choice of license, a recipient has the option to distribute
+# your version of this file under either the CDDL, the GPL Version 2 or
+# to extend the choice of license to its licensees as provided above.
+# However, if you add GPL Version 2 code and therefore, elected the GPL
+# Version 2 license, then the option applies only if the new code is
+# made subject to such option by the copyright holder.
+#
+# Contributor(s): Andrei Badea
+# Petr Hrebejk
+
+OpenIDE-Module-Name=Jump To
+OpenIDE-Module-Display-Category=Editing
+OpenIDE-Module-Short-Description=An action to quickly \
+ navigate to a file or a type
+OpenIDE-Module-Long-Description=This module provides actions which allows to \
+ navigate to a file in an open project by entering its name, or a type \
+ by entering its type name or a regular expression or CamelCase name.
+QuickSearch/GoToType=Go To Type
+QuickSearch/GoToSymbol=Go To Symbol
+
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/edit_parameters.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/edit_parameters.png
new file mode 100644
index 0000000..bed172b
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/edit_parameters.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/find.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/find.png
new file mode 100644
index 0000000..1039928
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/find.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/layer.xml b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/layer.xml
new file mode 100644
index 0000000..356a4f6
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/layer.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
+
+Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+Other names may be trademarks of their respective owners.
+
+
+The contents of this file are subject to the terms of either the GNU
+General Public License Version 2 only ("GPL") or the Common
+Development and Distribution License("CDDL") (collectively, the
+"License"). You may not use this file except in compliance with the
+License. You can obtain a copy of the License at
+http://www.netbeans.org/cddl-gplv2.html
+or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+specific language governing permissions and limitations under the
+License. When distributing the software, include this License Header
+Notice in each file and include the License file at
+nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the GPL Version 2 section of the License file that
+accompanied this code. If applicable, add the following below the
+License Header, with the fields enclosed by brackets [] replaced by
+your own identifying information:
+"Portions Copyrighted [year] [name of copyright owner]"
+
+Contributor(s):
+
+The Original Software is the Accelerators module.
+The Initial Developer of the Original Software is Andrei Badea.
+Portions Copyright 2005-2006 Andrei Badea.
+All Rights Reserved.
+
+If you wish your version of this file to be governed by only the CDDL
+or only the GPL Version 2, indicate your decision by adding
+"[Contributor] elects to include this software in this distribution
+under the [CDDL or GPL Version 2] license." If you do not indicate a
+single choice of license, a recipient has the option to distribute
+your version of this file under either the CDDL, the GPL Version 2 or
+to extend the choice of license to its licensees as provided above.
+However, if you add GPL Version 2 code and therefore, elected the GPL
+Version 2 license, then the option applies only if the new code is
+made subject to such option by the copyright holder.
+
+Contributor(s): Andrei Badea, Leon Chiver
+-->
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
+<filesystem>
+
+ <!-- Install the action -->
+ <folder name="Actions">
+ <folder name="Edit">
+ <!-- attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.project.ui.Bundle" / -->
+ <file name="org-netbeans-modules-jumpto-type-GoToType.instance">
+ <attr name="instanceClass" stringvalue="org.netbeans.modules.jumpto.type.GoToTypeAction"/>
+ </file>
+ <file name="org-netbeans-modules-jumpto-symbol-GoToSymbol.instance">
+ <attr name="instanceClass" stringvalue="org.netbeans.modules.jumpto.symbol.GoToSymbolAction"/>
+ </file>
+ </folder>
+ <folder name="Tools">
+ <file name="org-netbeans-modules-jumpto-file-FileSearchAction.instance"/>
+ </folder>
+ </folder>
+
+ <!-- Register the menu item -->
+ <folder name="Menu">
+
+ <folder name="GoTo">
+ <file name="org-netbeans-modules-jumpto-file-FileSearchAction.shadow">
+ <attr name="originalFile" stringvalue="Actions/Tools/org-netbeans-modules-jumpto-file-FileSearchAction.instance"/>
+ <attr name="position" intvalue="100"/>
+ </file>
+ <file name="org-netbeans-modules-jumpto-type-GoToType.shadow">
+ <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-jumpto-type-GoToType.instance"/>
+ <attr name="position" intvalue="150"/>
+ </file>
+ <file name="org-netbeans-modules-jumpto-symbol-GoToSymbol.shadow">
+ <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-jumpto-symbol-GoToSymbol.instance"/>
+ <attr name="position" intvalue="151"/>
+ </file>
+ </folder>
+ </folder>
+
+ <!-- Install the action shortcuts -->
+ <!--
+ <folder name="Keymaps">
+ <folder name="NetBeans">
+ <file name="OS-O.shadow">
+ <attr name="originalFile" stringvalue="Actions/Tools/org-netbeans-modules-jumpto-file-FileSearchAction.instance"/>
+ </file>
+ <file name="D-O.shadow">
+ <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-jumpto-type-GoToType.instance"/>
+ </file>
+ </folder>
+ </folder>
+ -->
+
+
+ <folder name="Editors">
+ <file name="org-netbeans-modules-jumpto-file-FileIndexer$Factory.instance">
+ <attr name="instaceOf" stringvalue="org.netbeans.modules.parsing.spi.indexing.CustomIndexerFactory"/>
+ </file>
+ </folder>
+
+ <folder name="OptionsDialog">
+ <!-- This is highly suspicious, but it was this way in java/source - Hrebejk, can you check this? -->
+ <folder name="Actions">
+ <folder name="GoTo">
+ <file name="GoToType.shadow">
+ <attr name="originalFile" stringvalue="Actions/Edit/org-netbeans-modules-jumpto-type-GoToType.instance"/>
+ </file>
+ </folder>
+ </folder>
+ </folder>
+
+ <folder name="QuickSearch">
+ <folder name="GoToType">
+ <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.jumpto.resources.Bundle"/>
+ <attr name="command" stringvalue="t"/>
+ <attr name="position" intvalue="300"/>
+ <file name="org-netbeans-modules-jumpto-quicksearch-JavaTypeSearchProvider.instance"/>
+ </folder>
+ <folder name="GoToSymbol">
+ <attr name="SystemFileSystem.localizingBundle" stringvalue="org.netbeans.modules.jumpto.resources.Bundle"/>
+ <attr name="command" stringvalue="s"/>
+ <attr name="position" intvalue="350"/>
+ <file name="org-netbeans-modules-jumpto-quicksearch-GoToSymbolProvider.instance"/>
+ </folder>
+
+ </folder>
+</filesystem>
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/unknown.gif b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/unknown.gif
new file mode 100644
index 0000000..9bed852
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/unknown.gif
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/wait.gif b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/wait.gif
new file mode 100644
index 0000000..e989393
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/wait.gif
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/warning.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/warning.png
new file mode 100644
index 0000000..518bc52
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/navigation/warning.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/org-jetbrains-kotlin-debugger-KotlinToggleBreakpointAction.shadow b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/org-jetbrains-kotlin-debugger-KotlinToggleBreakpointAction.shadow
new file mode 100644
index 0000000..d1fbe80
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/org-jetbrains-kotlin-debugger-KotlinToggleBreakpointAction.shadow
@@ -0,0 +1 @@
+file:/UNKNOWN
\ No newline at end of file
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/src_packages.png b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/src_packages.png
new file mode 100644
index 0000000..322ad23
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/src_packages.png
Binary files differ
diff --git a/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/wizards/java/javaFile.html b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/wizards/java/javaFile.html
new file mode 100644
index 0000000..ce2f522
--- /dev/null
+++ b/contrib/kotlin/src/main/resources/org/jetbrains/kotlin/wizards/java/javaFile.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+Copyright 2000-2018 JetBrains s.r.o.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ <!--
+ TODO replace this with a description what your wizard is supposed to do.
+ This information will be displayed in the New Wizard Description area.
+ -->
+ </body>
+</html>
diff --git a/contrib/kotlin/src/test/java/completion/CompletionTest.kt b/contrib/kotlin/src/test/java/completion/CompletionTest.kt
new file mode 100644
index 0000000..a95e6bc
--- /dev/null
+++ b/contrib/kotlin/src/test/java/completion/CompletionTest.kt
@@ -0,0 +1,72 @@
+package completion
+
+import utils.*
+import org.jetbrains.kotlin.completion.*
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.utils.ProjectUtils
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+class CompletionTest : KotlinTestCase("Completion test", "completion") {
+
+ private fun doTest(fileName: String, items: Collection<String> = emptyList()) {
+ val doc = getDocumentForFileObject(dir, fileName)
+ val caret = getCaret(doc)
+ assertNotNull(caret)
+
+ val file = ProjectUtils.getFileObjectForDocument(doc)
+ val ktFile = KotlinPsiManager.getParsedFile(file)!!
+
+ val resultWithProvider = KotlinAnalyzer.analyzeFile(project, ktFile)
+
+ val completionItems = createProposals(doc, caret, resultWithProvider, "")
+ assertNotNull(completionItems)
+
+ val completions = completionItems.map { it.sortText }
+ assertEquals(true, completions.containsAll(items))
+ }
+
+ fun testStringCompletion() = doTest("checkStringCompletion.kt", listOf("toString()"))
+
+ fun testBasicInt() = doTest("checkBasicInt.kt", listOf("Int"))
+
+ fun testBasicAny() = doTest("checkBasicAny.kt", listOf("Any"))
+
+ fun testAutoCastAfterIf() = doTest("checkAutoCastAfterIf.kt", listOf("value"))
+
+ fun testAutoCastAfterIfMethod() = doTest("checkAutoCastAfterIfMethod.kt", listOf("test()"))
+
+ fun testAutoCastForThis() = doTest("checkAutoCastForThis.kt", listOf("destroy()"))
+
+ fun testAutoCastInWhen() = doTest("checkAutoCastInWhen.kt", listOf("left", "right"))
+
+ fun testCompletionBeforeDotInCall() = doTest("checkCompletionBeforeDotInCall.kt", listOf("TestSample", "testVar", "testTop()", "testFun()"))
+
+ fun testLocalLambda() = doTest("checkLocalLambda.kt", listOf("test()"))
+
+ fun testCompanion() = doTest("checkCompanion.kt", listOf("companionVal", "companionFun()"))
+
+ fun testExtendsClass() = doTest("checkExtendClass.kt", listOf("MyFirstClass", "MySecondClass"))
+
+ fun testImport() = doTest("checkImport.kt", listOf("Proxy"))
+
+ fun testInCallExpression() = doTest("checkInCallExpression.kt", listOf("func()"))
+
+ fun testInClassInit() = doTest("checkInClassInit.kt", listOf("valExternal", "valInternal"))
+
+ fun testInClassPropertyAccessor() = doTest("checkInClassPropertyAccessor.kt", listOf("test", "testParam"))
+
+ fun testInImport() = doTest("checkInImport.kt", listOf("Proxy", "Base"))
+
+ fun testInParameterType() = doTest("checkInParameterType.kt", listOf("Int"))
+
+ fun testUpperAndLowerCase() = doTest("checkUpperAndLowerCases.kt", listOf("method()"))
+
+ fun testNonImported() = doTest("checkUnimported.kt", listOf("completion.pack.function1", "completion.pack.function2"))
+
+ fun testNonImportedPrivate() = doTest("checkNonImportedPrivate.kt")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/diagnostics/DiagnosticsTest.kt b/contrib/kotlin/src/test/java/diagnostics/DiagnosticsTest.kt
new file mode 100644
index 0000000..68fd41b
--- /dev/null
+++ b/contrib/kotlin/src/test/java/diagnostics/DiagnosticsTest.kt
@@ -0,0 +1,89 @@
+package diagnostics
+
+import utils.*
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.jetbrains.kotlin.diagnostics.Severity
+import org.jetbrains.kotlin.resolve.AnalyzingUtils
+import org.openide.filesystems.FileObject
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+class DiagnosticsTest : KotlinTestCase("Diagnostics test", "diagnostics") {
+
+ private fun getAnalysisResult(fileName: String): AnalysisResultWithProvider {
+ val fileToAnalyze = dir.getFileObject(fileName)
+ assertNotNull(fileToAnalyze)
+
+ val ktFile = ProjectUtils.getKtFile(fileToAnalyze)
+ return KotlinAnalyzer.analyzeFile(project, ktFile)
+ }
+
+ private fun doTest(fileName: String,
+ diagnosticsRanges: List<Pair<Int, Int>>,
+ diagnosticsSeverity: List<Severity>,
+ syntaxErrorsRanges: List<Pair<Int, Int>>) {
+ val numberOfDiagnostics = diagnosticsRanges.size
+ val numberOfSyntaxErrors = syntaxErrorsRanges.size
+
+ val result = getAnalysisResult(fileName)
+ val fileToAnalyze = dir.getFileObject(fileName)
+ val ktFile = ProjectUtils.getKtFile(fileToAnalyze)
+
+ val diagnostics = result.analysisResult.bindingContext.diagnostics.all()
+ val syntaxErrors = AnalyzingUtils.getSyntaxErrorRanges(ktFile)
+
+ assertEquals(numberOfDiagnostics, diagnostics.size)
+ assertEquals(numberOfSyntaxErrors, syntaxErrors.size)
+
+ diagnostics.forEachIndexed { i, it ->
+ assertEquals(diagnosticsSeverity[i], it.severity)
+
+ val startPosition = it.textRanges[0].startOffset
+ val endPosition = it.textRanges[0].endOffset
+
+ assertEquals(diagnosticsRanges[i].first, startPosition)
+ assertEquals(diagnosticsRanges[i].second, endPosition)
+ }
+
+ syntaxErrors.forEachIndexed { i, it ->
+ val startPosition = it.textRange.startOffset
+ val endPosition = it.textRange.endOffset
+
+ assertEquals(syntaxErrorsRanges[i].first, startPosition)
+ assertEquals(syntaxErrorsRanges[i].second, endPosition)
+ }
+
+ }
+
+ private fun doTest(fileName: String,
+ diagnosticsRanges: List<Pair<Int, Int>>,
+ diagnosticsSeverity: List<Severity>) = doTest(fileName, diagnosticsRanges, diagnosticsSeverity, emptyList())
+
+ private fun doTest(fileName: String,
+ syntaxErrorsRanges: List<Pair<Int, Int>> = emptyList()) = doTest(fileName, emptyList(), emptyList(), syntaxErrorsRanges)
+
+ fun testKtHome() = assertNotNull(ProjectUtils.KT_HOME)
+
+ fun testParameterIsNeverUsedWarning() = doTest("parameterIsNeverUsed.kt", listOf(Pair(30, 33)), listOf(Severity.WARNING))
+
+ fun testExpectingATopLevelDeclarationError() = doTest("expectingATopLevelDeclaration.kt", listOf(Pair(21, 31)))
+
+ fun testNoTypeMismatch() = doTest("checkNoTypeMismatch.kt")
+
+ fun testTypeMismatch() = doTest("checkTypeMismatch.kt", listOf(Pair(151, 172)), listOf(Severity.ERROR))
+
+ fun testNoValuePassed() = doTest("checkNoValuePassed.kt", listOf(Pair(80, 81)), listOf(Severity.ERROR))
+
+ fun testWrongImport() = doTest("checkWrongImport.kt", listOf(Pair(28, 32)), listOf(Severity.ERROR))
+
+ fun testCheckNullPointer() = doTest("checkNullPointer.kt", listOf(Pair(86, 90)), listOf(Severity.ERROR))
+
+ fun testReassignValue() = doTest("checkReassignValue.kt", listOf(Pair(61, 66)), listOf(Severity.ERROR))
+
+ fun testCastIsNeverSucceed() = doTest("checkCastIsNeverSucceed.kt", listOf(Pair(95, 97), Pair(79, 82)), listOf(Severity.WARNING, Severity.WARNING))
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/formatting/FormattingTest.kt b/contrib/kotlin/src/test/java/formatting/FormattingTest.kt
new file mode 100644
index 0000000..60f5bfc
--- /dev/null
+++ b/contrib/kotlin/src/test/java/formatting/FormattingTest.kt
@@ -0,0 +1,85 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package formatting
+
+import com.intellij.psi.PsiFile
+import javaproject.JavaProject
+import javax.swing.text.Document
+import org.jetbrains.kotlin.formatting.KotlinFormatterUtils
+import org.jetbrains.kotlin.formatting.NetBeansDocumentFormattingModel
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.Project
+import org.openide.filesystems.FileObject
+import utils.*
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+class FormattingTest : KotlinTestCase("Formatting test", "formatting") {
+
+ private fun doTest(fileName: String) {
+ val doc = getDocumentForFileObject(dir, fileName)
+ val file = ProjectUtils.getFileObjectForDocument(doc)
+ val parsedFile = ProjectUtils.getKtFile(doc.getText(0, doc.length), file)
+ val code = parsedFile.text
+
+ val formattedCode = KotlinFormatterUtils.formatCode(code, parsedFile.name, project, "\n")
+ val doc2 = getDocumentForFileObject(dir, fileName.replace(".kt", ".after"))
+ val after = doc2.getText(0, doc2.length)
+ assertEquals(after, formattedCode)
+ }
+
+ fun testBlockCommentBeforeDeclaration() = doTest("blockCommentBeforeDeclaration.kt")
+
+ fun testClassesAndPropertiesFormatTest() = doTest("classesAndPropertiesFormatTest.kt")
+
+ fun testCommentOnTheLastLineOfLambda() = doTest("commentOnTheLastLineOfLambda.kt")
+
+ fun testIndentInDoWhile() = doTest("indentInDoWhile.kt")
+
+ fun testIndentInIfExpressionBlock() = doTest("indentInIfExpressionBlock.kt")
+
+ fun testIndentInPropertyAccessor() = doTest("indentInPropertyAccessor.kt")
+
+ fun testIndentInWhenEntry() = doTest("indentInWhenEntry.kt")
+
+ fun testInitIndent() = doTest("initIndent.kt")
+
+ fun testLambdaInBlock() = doTest("lambdaInBlock.kt")
+
+ fun testNewLineAfterImportsAndPackage() = doTest("newLineAfterImportsAndPackage.kt")
+
+ fun testObjectsAndLocalFunctionsFormat() = doTest("objectsAndLocalFunctionsFormatTest.kt")
+
+ fun testPackageFunctions() = doTest("packageFunctionsFormatTest.kt")
+
+ fun testClassInBlockComment() = doTest("withBlockComments.kt")
+
+ fun testJavaDoc() = doTest("withJavaDoc.kt")
+
+ fun testLineComments() = doTest("withLineComments.kt")
+
+ fun testMutableVariable() = doTest("withMutableVariable.kt")
+
+ fun testWhitespaceBeforeBrace() = doTest("withWhitespaceBeforeBrace.kt")
+
+ fun testWhithoutComments() = doTest("withoutComments.kt")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/highlighting/HighlightingTest.kt b/contrib/kotlin/src/test/java/highlighting/HighlightingTest.kt
new file mode 100644
index 0000000..5e7bc1a
--- /dev/null
+++ b/contrib/kotlin/src/test/java/highlighting/HighlightingTest.kt
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package highlighting
+
+import javaproject.JavaProject
+import javax.swing.text.Document
+import org.jetbrains.kotlin.highlighter.KotlinTokenScanner
+import org.jetbrains.kotlin.highlighter.TokenType
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinToken
+import org.jetbrains.kotlin.highlighter.netbeans.KotlinTokenId
+import org.netbeans.api.project.Project
+import org.openide.filesystems.FileObject
+import utils.*
+
+class HighlightingTest : KotlinTestCase("Highlighting test", "highlighting") {
+
+ fun doTest(fileName: String, vararg types: TokenType) {
+ val doc = getDocumentForFileObject(dir, fileName)
+ val tokens = KotlinTokenScanner(doc.getText(0, doc.length)).tokens
+ assertNotNull(tokens)
+
+ val parsedTypes = tokens.map{ it.type }
+ .filter{ it != TokenType.EOF && it != TokenType.WHITESPACE
+ && it != TokenType.UNDEFINED && it != TokenType.IDENTIFIER }
+
+
+ assertEquals(parsedTypes, types.asList())
+ }
+
+ fun testBlockComment() = doTest("blockComment.kt", TokenType.MULTI_LINE_COMMENT)
+
+ fun testForKeyword() = doTest("forKeyword.kt", TokenType.KEYWORD)
+
+ fun testFunction() = doTest("function.kt", TokenType.KEYWORD, TokenType.KEYWORD)
+
+ fun testGetterSetter() {
+ doTest("getterSetter.kt", TokenType.KEYWORD, TokenType.KEYWORD,
+ TokenType.KEYWORD, TokenType.KEYWORD)
+ }
+
+ fun testCompanionObject() = doTest("companionObject.kt", TokenType.KEYWORD, TokenType.KEYWORD, TokenType.KEYWORD)
+
+ fun testImportKeyword() = doTest("importKeyword.kt", TokenType.KEYWORD)
+
+ fun testInKeyword() = doTest("inKeyword.kt", TokenType.KEYWORD)
+
+ fun testInterfaceKeyword() = doTest("interfaceKeyword.kt", TokenType.KEYWORD)
+
+ fun testKeywordWithText() = doTest("keywordWithText.kt", TokenType.KEYWORD)
+
+ fun testOpenKeyword() = doTest("openKeyword.kt", TokenType.KEYWORD, TokenType.KEYWORD)
+
+ fun testSingleLineComment() = doTest("singleLineComment.kt", TokenType.SINGLE_LINE_COMMENT)
+
+ fun testSoftImportKeyword() = doTest("softImportKeyword.kt", TokenType.KEYWORD)
+
+ fun testSoftKeywords() {
+ doTest("softKeywords.kt", TokenType.KEYWORD, TokenType.KEYWORD,
+ TokenType.KEYWORD, TokenType.KEYWORD)
+ }
+
+ fun testStringInterpolation() {
+ doTest("stringInterpolation.kt", TokenType.KEYWORD, TokenType.STRING,
+ TokenType.STRING, TokenType.STRING)
+ }
+
+ fun testStringToken() = doTest("stringToken.kt", TokenType.STRING, TokenType.STRING, TokenType.STRING)
+
+ fun testTextWithTokenInside() = doTest("textWithTokenInside.kt")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/indentation/IndentationTest.kt b/contrib/kotlin/src/test/java/indentation/IndentationTest.kt
new file mode 100644
index 0000000..3ca0dc2
--- /dev/null
+++ b/contrib/kotlin/src/test/java/indentation/IndentationTest.kt
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package indentation
+
+import javaproject.JavaProject
+import javax.swing.text.StyledDocument
+import org.jetbrains.kotlin.formatting.KotlinIndentStrategy
+import org.netbeans.api.project.Project
+import org.netbeans.junit.NbTestCase
+import org.openide.filesystems.FileObject
+import utils.*
+
+class IndentationTest : KotlinTestCase("Indentation test", "indentation") {
+
+ fun doTest(fileName: String) {
+ val doc = getDocumentForFileObject(dir, fileName) as StyledDocument
+ val offset = getCaret(doc) + 1
+ doc.remove(offset - 1, "<caret>".length)
+ doc.insertString(offset - 1, "\n", null)
+
+ val strategy = KotlinIndentStrategy(doc, offset)
+ val newOffset = strategy.addIndent()
+
+ val doc2 = getDocumentForFileObject(dir, fileName.replace(".kt", ".after"))
+ val expectedOffset = getCaret(doc2)
+
+ assertEquals(expectedOffset, newOffset)
+ }
+
+ fun testAfterOneOpenBrace() = doTest("afterOneOpenBrace.kt")
+
+ fun testBeforeFunctionStart() = doTest("beforeFunctionStart.kt")
+
+ fun testBetweenBracesOnDifferentLines() = doTest("betweenBracesOnDifferentLine.kt")
+
+ fun testBreakLineAfterIfWithoutBraces() = doTest("breakLineAfterIfWithoutBraces.kt")
+
+ fun testAfterOperatorIfWithoutBraces() = doTest("afterOperatorIfWithoutBraces.kt")
+
+ fun testAfterOperatorWhileWithoutBraces() = doTest("afterOperatorWhileWithoutBraces.kt")
+
+ fun testBeforeCloseBrace() = doTest("beforeCloseBrace.kt")
+
+ fun testContinuationAfterDotCall() = doTest("continuationAfterDotCall.kt")
+
+ fun testContinuationBeforeFunName() = doTest("continuationBeforeFunName.kt")
+
+ fun testBeforeNestedCloseBrace() = doTest("beforeNestedCloseBrace.kt")
+
+ fun testBeforeTwiceNestedCloseBrace() = doTest("beforeTwiceNestedCloseBrace.kt")
+
+ fun testAfterEquals() = doTest("afterEquals.kt")
+
+ fun testIndentBeforeWhile() = doTest("indentBeforeWhile.kt")
+
+ fun testLineBreakSaveIndent() = doTest("lineBreakSaveIndent.kt")
+
+ fun testNestedOperatorsWithBraces() = doTest("nestedOperatorsWithBraces.kt")
+
+ fun testNestedOperatorsWithoutBraces() = doTest("nestedOperatorsWithoutBraces.kt")
+
+ fun testNewLineInParameters() = doTest("newLineInParameters.kt")
+
+ fun testNewLineWhenCaretAtPosition0() = doTest("newLineWhenCaretAtPosition0.kt")
+
+// fun testBetweenBracesOnOneLine() = doTest("betweenBracesOnOneLine.kt")
+//
+// fun testBetweenBracesOnOneLine2() = doTest("betweenBracesOnOneLine2.kt")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/intentions/IntentionsTest.kt b/contrib/kotlin/src/test/java/intentions/IntentionsTest.kt
new file mode 100644
index 0000000..28e5f52
--- /dev/null
+++ b/contrib/kotlin/src/test/java/intentions/IntentionsTest.kt
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package intentions
+
+import utils.*
+import org.openide.filesystems.FileObject
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.hints.intentions.*
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+
+class IntentionsTest : KotlinTestCase("Intentions test", "intentions") {
+
+ private fun doTest(fileName: String, intention: Class<out ApplicableIntention>, applicable: Boolean = true) {
+ val caret = getCaret(getDocumentForFileObject(dir, "$fileName.caret"))
+ assertNotNull(caret)
+
+ val doc = getDocumentForFileObject(dir, "$fileName.kt")
+ val file = dir.getFileObject("$fileName.kt")
+ val ktFile = KotlinPsiManager.getParsedFile(file)!!
+
+ val resultWithProvider = KotlinParser.getAnalysisResult(ktFile, project)!!
+
+ val psi = ktFile.findElementAt(caret) ?: assert(false)
+
+ val applicableIntention = intention.constructors.first().newInstance(doc, resultWithProvider.analysisResult, psi) as ApplicableIntention
+
+ assertEquals(applicable, applicableIntention.isApplicable(caret))
+
+ applicableIntention.implement()
+ assertTrue(doc.getText(0, doc.length) equalsWithoutSpaces dir.getFileObject("$fileName.after").asText())
+ }
+
+ fun testRemoveEmptyClassBody() = doTest("removeEmptyClassBody", RemoveEmptyClassBodyIntention::class.java)
+
+ fun testToInfix() = doTest("toInfix", ToInfixIntention::class.java)
+
+ fun testSpecifyType() = doTest("specifyType", SpecifyTypeIntention::class.java)
+
+ fun testAddValToConstructorParameter() = doTest("addValToConstructorParameter", AddValToConstructorParameterIntention::class.java)
+
+ fun testChangeReturnType() = doTest("changeReturnType", ChangeReturnTypeIntention::class.java)
+
+ fun testConvertToSealedClass() = doTest("convertToSealedClass", ConvertEnumToSealedClassIntention::class.java)
+
+ fun testConvertPropertyInitializerToGetter() = doTest("convertPropertyInitializerToGetter", ConvertPropertyInitializerToGetterIntention::class.java)
+
+ fun testConvertToBlockBody() = doTest("convertToBlockBody", ConvertToBlockBodyIntention::class.java)
+
+ fun testConvertToStringTemplate() = doTest("convertToStringTemplate", ConvertToStringTemplateIntention::class.java)
+
+ fun testConvertToExpressionBody() = doTest("convertToExpressionBody", ConvertToExpressionBodyIntention::class.java)
+
+ fun testConvertTwoComparisonsToRangeCheck() = doTest("convertTwoComparisons", ConvertTwoComparisonsToRangeCheckIntention::class.java)
+
+ fun testMergeIfsIntention() = doTest("mergeIfs", MergeIfsIntention::class.java)
+
+ fun testRemoveBraces() = doTest("removeBraces", RemoveBracesIntention::class.java)
+
+ fun testRemoveParenthesesFromLambdaCall() = doTest("removeParenthesesFromLambdaCall", RemoveEmptyParenthesesFromLambdaCallIntention::class.java)
+
+ fun testRemoveEmptyPrimaryConstructor() = doTest("removeEmptyPrimaryConstructor", RemoveEmptyPrimaryConstructorIntention::class.java)
+
+ fun testRemoveEmptySecondaryConstructor() = doTest("removeEmptySecondaryConstructor", RemoveEmptySecondaryConstructorIntention::class.java)
+
+ fun testRemoveExplicitType() = doTest("removeExplicitType", RemoveExplicitTypeIntention::class.java)
+
+ fun testReplaceSizeCheckWithIsNotEmpty() = doTest("replaceSizeCheckWithIsNotEmpty", ReplaceSizeCheckWithIsNotEmptyIntention::class.java)
+
+ fun testSplitIf() = doTest("splitIf", SplitIfIntention::class.java)
+
+ fun testConvertToConcatenatedString() = doTest("convertToConcatenatedString", ConvertToConcatenatedStringIntention::class.java)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/j2k/J2KTest.kt b/contrib/kotlin/src/test/java/j2k/J2KTest.kt
new file mode 100644
index 0000000..aa32616
--- /dev/null
+++ b/contrib/kotlin/src/test/java/j2k/J2KTest.kt
@@ -0,0 +1,50 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package j2k
+
+import javaproject.JavaProject
+import javax.swing.text.Document
+import org.jetbrains.kotlin.j2k.Java2KotlinConverter
+import org.netbeans.api.project.Project
+import org.openide.filesystems.FileObject
+import utils.*
+
+class J2KTest : KotlinTestCase("Converter test", "j2k") {
+
+ private fun doTest(fileName: String) {
+ val javaFile = dir.getFileObject("$fileName.java")
+ val doc = getDocumentForFileObject(dir, "$fileName.java")
+ Java2KotlinConverter.convert(doc, project, javaFile)
+
+ val kotlinDoc = getDocumentForFileObject(dir, "$fileName.kt")
+ val afterDoc = getDocumentForFileObject(dir, "$fileName.after")
+ val kotlinText = kotlinDoc.getText(0, kotlinDoc.length)
+ val afterText = afterDoc.getText(0, afterDoc.length)
+ assertEquals(afterText, kotlinText)
+ }
+
+ fun testSimpleCase() = doTest("simple")
+
+ fun testWithStaticMethods() = doTest("withStaticMethod")
+
+ fun testMixed() = doTest("mixed")
+
+ fun testWithInnerClass() = doTest("withInnerClass")
+
+ fun testInterface() = doTest("interface")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javaproject/JavaAntBasedProjectType.java b/contrib/kotlin/src/test/java/javaproject/JavaAntBasedProjectType.java
new file mode 100644
index 0000000..a8c2f58
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/JavaAntBasedProjectType.java
@@ -0,0 +1,41 @@
+package javaproject;
+
+import java.io.IOException;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.support.ant.AntBasedProjectType;
+import org.netbeans.spi.project.support.ant.AntProjectHelper;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+@org.openide.util.lookup.ServiceProvider(service = AntBasedProjectType.class, position = 1)
+public class JavaAntBasedProjectType implements AntBasedProjectType{
+
+ public static final String TYPE = "org.netbeans.modules.java.j2seproject";
+ static final String PROJECT_CONFIGURATION_NAME = "data";
+ public static final String PROJECT_CONFIGURATION_NAMESPACE = "http://www.netbeans.org/ns/j2se-project/3";
+ static final String PRIVATE_CONFIGURATION_NAME = "data";
+ static final String PRIVATE_CONFIGURATION_NAMESPACE = "http://www.netbeans.org/ns/j2se-project-private/1";
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Project createProject(AntProjectHelper helper) throws IOException {
+ return new org.netbeans.modules.java.j2seproject.J2SEProject(helper);
+ }
+
+ @Override
+ public String getPrimaryConfigurationDataElementName(boolean shared) {
+ return shared ? PROJECT_CONFIGURATION_NAME : PRIVATE_CONFIGURATION_NAME;
+ }
+
+ @Override
+ public String getPrimaryConfigurationDataElementNamespace(boolean shared) {
+ return shared ? PROJECT_CONFIGURATION_NAMESPACE : PRIVATE_CONFIGURATION_NAMESPACE;
+ }
+
+}
diff --git a/contrib/kotlin/src/test/java/javaproject/JavaProject.kt b/contrib/kotlin/src/test/java/javaproject/JavaProject.kt
new file mode 100644
index 0000000..0f709c3
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/JavaProject.kt
@@ -0,0 +1,46 @@
+package javaproject
+
+import javaproject.mockservices.MockActiveDocumentProvider
+import javaproject.mockservices.MockEditorMimeTypesImpl
+import javaproject.mockservices.MockKotlinParserFactory
+import javaproject.mockservices.MockOpenProjectsTrampoline
+import javaproject.mockservices.TestEnvironmentFactory
+import org.netbeans.api.java.platform.JavaPlatformManager
+import org.netbeans.api.project.Project
+import org.netbeans.api.project.ProjectManager
+import org.netbeans.api.project.ui.OpenProjects
+import org.netbeans.junit.MockServices
+import org.netbeans.junit.NbTestCase
+import org.netbeans.modules.java.source.parsing.JavacParserFactory
+import org.netbeans.modules.project.ant.AntBasedProjectFactorySingleton
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+object JavaProject : NbTestCase("Java project") {
+ val javaProject: Project
+
+ init {
+ createMockLookup()
+ javaProject = createJavaProject()
+ OpenProjects.getDefault().open(arrayOf<Project>(javaProject), false)
+ }
+
+ private fun createJavaProject(): Project {
+ return ProjectManager.getDefault().findProject(JavaProjectUnzipper.INSTANCE.getTestProject())
+ }
+
+ private fun createMockLookup() {
+ MockServices.setServices(JavaAntBasedProjectType::class.java,
+ AntBasedProjectFactorySingleton::class.java,
+ org.netbeans.modules.project.ant.StandardAntArtifactQueryImpl::class.java,
+ TestEnvironmentFactory::class.java,
+ MockKotlinParserFactory::class.java,
+ MockActiveDocumentProvider::class.java,
+ MockOpenProjectsTrampoline::class.java,
+ JavaPlatformManager::class.java,
+ JavacParserFactory::class.java,
+ MockEditorMimeTypesImpl::class.java)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javaproject/JavaProjectUnzipper.java b/contrib/kotlin/src/test/java/javaproject/JavaProjectUnzipper.java
new file mode 100644
index 0000000..b00622e
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/JavaProjectUnzipper.java
@@ -0,0 +1,102 @@
+package javaproject;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.jetbrains.kotlin.utils.ProjectUtils;
+import org.netbeans.junit.NbTestCase;
+import org.openide.filesystems.FileLock;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+public class JavaProjectUnzipper extends NbTestCase {
+
+ public static JavaProjectUnzipper INSTANCE = new JavaProjectUnzipper("ProjectUnzipper");
+
+ private JavaProjectUnzipper(String name) {
+ super(name);
+ }
+
+ private void unZipFile(File archiveFile, FileObject destDir) throws IOException {
+ FileInputStream fis = new FileInputStream(archiveFile);
+ try {
+ ZipInputStream str = new ZipInputStream(fis);
+ ZipEntry entry;
+ while ((entry = str.getNextEntry()) != null) {
+ if (entry.isDirectory()) {
+ FileUtil.createFolder(destDir, entry.getName());
+ } else {
+ FileObject fo = FileUtil.createData(destDir, entry.getName());
+ FileLock lock = fo.lock();
+ try {
+ OutputStream out = fo.getOutputStream(lock);
+ try {
+ FileUtil.copy(str, out);
+ } finally {
+ out.close();
+ }
+ } finally {
+ lock.releaseLock();
+ }
+ }
+ }
+ } finally {
+ fis.close();
+ }
+
+ }
+
+ private FileObject getUnzippedFolder(String path) throws IOException {
+ assertNotNull(path);
+ File archiveFile = new File(path);
+ FileObject destFileObject = FileUtil.toFileObject(getWorkDir());
+ unZipFile(archiveFile, destFileObject);
+ assertTrue(destFileObject.isValid());
+
+ String folderName = "kotlinc";
+
+ FileObject unzippedFolder = destFileObject.getFileObject(folderName);
+ assertNotNull(unzippedFolder);
+
+ return unzippedFolder;
+ }
+
+ public FileObject getTestProject() throws IOException {
+ getKtHomeForTests();
+ String path = "." + ProjectUtils.FILE_SEPARATOR + "src" + ProjectUtils.FILE_SEPARATOR +
+ "test" + ProjectUtils.FILE_SEPARATOR + "resources" + ProjectUtils.FILE_SEPARATOR + "projForTest";
+
+ File projectFile = new File(path);
+ FileObject projectFileObject = FileUtil.toFileObject(FileUtil.normalizeFile(projectFile));
+ FileObject destFileObject = FileUtil.toFileObject(getWorkDir());
+
+ FileObject testProject = destFileObject.getFileObject("projForTest");
+ if (testProject != null) {
+ testProject.delete();
+ }
+
+ testProject = FileUtil.copyFile(projectFileObject, destFileObject, "projForTest");
+
+ return testProject;
+ }
+
+ private void getKtHomeForTests() throws IOException {
+ String path = "." + ProjectUtils.FILE_SEPARATOR + "src" + ProjectUtils.FILE_SEPARATOR + "main" +
+ ProjectUtils.FILE_SEPARATOR + "resources" + ProjectUtils.FILE_SEPARATOR + "org" +
+ ProjectUtils.FILE_SEPARATOR + "jetbrains" + ProjectUtils.FILE_SEPARATOR + "kotlin" + ProjectUtils.FILE_SEPARATOR +
+ "kotlinc" + ProjectUtils.FILE_SEPARATOR + "kotlinc.zip";
+ FileObject kotlincFolder = getUnzippedFolder(path);
+
+ ProjectUtils.KT_HOME = kotlincFolder.getPath() + ProjectUtils.FILE_SEPARATOR;
+ }
+
+}
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/MockActiveDocumentProvider.java b/contrib/kotlin/src/test/java/javaproject/mockservices/MockActiveDocumentProvider.java
new file mode 100644
index 0000000..d3651e0
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/MockActiveDocumentProvider.java
@@ -0,0 +1,176 @@
+package javaproject.mockservices;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.swing.SwingUtilities;
+import javax.swing.text.Document;
+import javax.swing.text.JTextComponent;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
+import org.netbeans.api.editor.EditorRegistry;
+import org.netbeans.modules.parsing.impl.indexing.implspi.ActiveDocumentProvider;
+import org.openide.util.Parameters;
+import org.openide.util.WeakListeners;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author Tomas Zezula
+ */
+@ServiceProvider(service = ActiveDocumentProvider.class, position = 30000)
+public final class MockActiveDocumentProvider implements ActiveDocumentProvider, PropertyChangeListener {
+
+ private final AtomicBoolean listens;
+ private final List<ActiveDocumentListener> listeners;
+ //Threading: accessed only from EDT
+ private Reference<JTextComponent> activeComponentRef;
+
+ public MockActiveDocumentProvider() {
+ this.listens = new AtomicBoolean();
+ this.listeners = new CopyOnWriteArrayList<ActiveDocumentListener>();
+ }
+
+ @Override
+ @CheckForNull
+ public Document getActiveDocument() {
+ final JTextComponent last = EditorRegistry.lastFocusedComponent();
+ return last == null ?
+ null :
+ last.getDocument();
+ }
+
+ @Override
+ public Set<? extends Document> getActiveDocuments() {
+ final Set<Document> res = Collections.newSetFromMap(new IdentityHashMap<Document, Boolean>());
+ for (JTextComponent jtc : EditorRegistry.componentList()) {
+ final Document doc = jtc.getDocument();
+ if (doc != null) {
+ res.add(doc);
+ }
+ }
+ return res;
+ }
+
+ @Override
+ public void addActiveDocumentListener(@NonNull final ActiveDocumentListener listener) {
+ Parameters.notNull("listener", listener); //NOI18N
+ attachListener();
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeActiveDocumentListener(@NonNull final ActiveDocumentListener listener) {
+ Parameters.notNull("listener", listener); //NOI18N
+ listeners.remove(listener);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ assert SwingUtilities.isEventDispatchThread() : "Changes in focused editor component should be delivered on AWT"; //NOI18N
+ Document deactivate = null, activate = null;
+ List<? extends JTextComponent> components = Collections.<JTextComponent>emptyList();
+ boolean steady = false;
+ final String propName = evt.getPropertyName();
+ if (propName == null) {
+ components = EditorRegistry.componentList();
+ } else if (propName.equals(EditorRegistry.FOCUS_LOST_PROPERTY) ||
+ propName.equals(EditorRegistry.LAST_FOCUSED_REMOVED_PROPERTY)) {
+ if (evt.getOldValue() instanceof JTextComponent) {
+ Object newValue = evt.getNewValue();
+ if (!(newValue instanceof JTextComponent) || ((JTextComponent)newValue).getClientProperty("AsTextField") == null) {
+ deactivate = ((JTextComponent) evt.getOldValue()).getDocument();
+ }
+ }
+ } else if (propName.equals(EditorRegistry.COMPONENT_REMOVED_PROPERTY)) {
+ if (evt.getOldValue() instanceof JTextComponent) {
+ JTextComponent jtc = (JTextComponent) evt.getOldValue();
+ components = Collections.singletonList(jtc);
+ steady = true;
+ }
+ } else if (propName.equals(EditorRegistry.FOCUS_GAINED_PROPERTY)) {
+ if (evt.getNewValue() instanceof JTextComponent) {
+ JTextComponent jtc = (JTextComponent) evt.getNewValue();
+ if (jtc.getClientProperty("AsTextField") == null) {
+ activate = jtc.getDocument();
+ JTextComponent activeComponent = activeComponentRef == null ? null : activeComponentRef.get();
+ if (activeComponent != jtc) {
+ if (activeComponent != null) {
+ components = Collections.singletonList(activeComponent);
+ }
+ activeComponentRef = new WeakReference<JTextComponent>(jtc);
+ }
+ }
+ }
+ } else if (propName.equals(EditorRegistry.FOCUSED_DOCUMENT_PROPERTY)) {
+ JTextComponent jtc = EditorRegistry.focusedComponent();
+ if (jtc == null) {
+ jtc = EditorRegistry.lastFocusedComponent();
+ }
+ if (jtc != null) {
+ components = Collections.singletonList(jtc);
+ }
+ deactivate = (Document) evt.getOldValue();
+ activate = (Document) evt.getNewValue();
+ }
+
+ fire(
+ deactivate,
+ activate,
+ map(
+ components,
+ new F<JTextComponent,Document>() {
+ @Override
+ public Document apply(JTextComponent jtc) {
+ return jtc.getDocument();
+ }
+ }),
+ steady);
+ }
+
+ private void attachListener() {
+ if (listens.compareAndSet(false, true)) {
+ EditorRegistry.addPropertyChangeListener(WeakListeners.propertyChange(this, EditorRegistry.class));
+ }
+ }
+
+ private void fire(
+ @NullAllowed final Document deactivated,
+ @NullAllowed final Document activated,
+ @NonNull final Collection<? extends Document> toRefresh,
+ final boolean steady) {
+ final ActiveDocumentEvent event = new ActiveDocumentEvent(
+ this,
+ deactivated,
+ activated,
+ toRefresh,
+ steady);
+ for (ActiveDocumentListener l : listeners) {
+ l.activeDocumentChanged(event);
+ }
+ }
+
+ private static <P,R> Collection<? extends R> map(
+ @NonNull final Collection<? extends P> elements,
+ @NonNull final F<? super P, ? extends R> fnc) {
+ final Collection<R> result = new ArrayList<R>(elements.size());
+ for (P p : elements) {
+ result.add(fnc.apply(p));
+ }
+ return result;
+ }
+
+ private static interface F<P,R> {
+ R apply(P p);
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/MockEditorMimeTypesImpl.java b/contrib/kotlin/src/test/java/javaproject/mockservices/MockEditorMimeTypesImpl.java
new file mode 100644
index 0000000..f7ed76f
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/MockEditorMimeTypesImpl.java
@@ -0,0 +1,74 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package javaproject.mockservices;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.Set;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.modules.editor.settings.storage.api.EditorSettings;
+import org.netbeans.spi.editor.document.EditorMimeTypesImplementation;
+import static org.netbeans.spi.editor.document.EditorMimeTypesImplementation.PROP_SUPPORTED_MIME_TYPES;
+import org.openide.util.Parameters;
+import org.openide.util.WeakListeners;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author Tomas Zezula
+ */
+@ServiceProvider(service = EditorMimeTypesImplementation.class)
+public final class MockEditorMimeTypesImpl implements EditorMimeTypesImplementation {
+
+ private final EditorSettings es;
+ private final PropertyChangeSupport listeners;
+ private final PropertyChangeListener listener;
+
+ public MockEditorMimeTypesImpl() {
+ this.es = EditorSettings.getDefault();
+ this.listeners = new PropertyChangeSupport(this);
+ this.listener = new PropertyChangeListener() {
+ @Override
+ public void propertyChange(@NonNull final PropertyChangeEvent evt) {
+ if (evt.getPropertyName() == null || EditorSettings.PROP_MIME_TYPES.equals(evt.getPropertyName())) {
+ listeners.firePropertyChange(PROP_SUPPORTED_MIME_TYPES, null, null);
+ }
+ }
+ };
+ this.es.addPropertyChangeListener(WeakListeners.propertyChange(listener, this.es));
+ }
+
+ @Override
+ public Set<String> getSupportedMimeTypes() {
+ return es.getAllMimeTypes();
+ }
+
+ @Override
+ public void addPropertyChangeListener(@NonNull final PropertyChangeListener listener) {
+ Parameters.notNull("listener", listener); //NOI18N
+ listeners.addPropertyChangeListener(listener);
+ }
+
+ @Override
+ public void removePropertyChangeListener(@NonNull final PropertyChangeListener listener) {
+ Parameters.notNull("listener", listener); //NOI18N
+ listeners.addPropertyChangeListener(listener);
+ }
+}
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/MockKotlinParserFactory.kt b/contrib/kotlin/src/test/java/javaproject/mockservices/MockKotlinParserFactory.kt
new file mode 100644
index 0000000..8d9177f
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/MockKotlinParserFactory.kt
@@ -0,0 +1,11 @@
+package javaproject.mockservices
+
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.KotlinParser
+import org.netbeans.modules.parsing.api.Snapshot
+import org.netbeans.modules.parsing.spi.Parser
+import org.netbeans.modules.parsing.spi.ParserFactory
+
+
+class MockKotlinParserFactory : ParserFactory() {
+ override fun createParser(snapshots: Collection<Snapshot>?) = KotlinParser()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/MockOpenProjectsTrampoline.kt b/contrib/kotlin/src/test/java/javaproject/mockservices/MockOpenProjectsTrampoline.kt
new file mode 100644
index 0000000..131a546
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/MockOpenProjectsTrampoline.kt
@@ -0,0 +1,51 @@
+package javaproject.mockservices
+
+import java.beans.PropertyChangeListener
+import org.netbeans.api.project.Project
+import org.netbeans.api.project.ProjectUtils
+import org.netbeans.api.project.ui.ProjectGroup
+import org.netbeans.api.project.ui.ProjectGroupChangeListener
+import org.netbeans.modules.project.uiapi.OpenProjectsTrampoline
+
+class MockOpenProjectsTrampoline : OpenProjectsTrampoline {
+
+ private val openProjects = arrayListOf<Project>()
+ private var mainProject: Project? = null
+
+ override fun getOpenProjectsAPI() = openProjects.toTypedArray()
+
+ override fun openAPI(projects: Array<Project>, openRequiredProjects: Boolean, bool: Boolean) {
+ openProjects.addAll(projects)
+ if (projects.size > 0) {
+ mainProject = projects.last()
+ }
+ }
+
+ override fun closeAPI(projects: Array<Project>) {
+ openProjects.removeAll(projects)
+ }
+
+ override fun addPropertyChangeListenerAPI(listener: PropertyChangeListener?, source: Any?) {
+ }
+
+ override fun removePropertyChangeListenerAPI(listener: PropertyChangeListener?) {
+ }
+
+ override fun getMainProject() = mainProject
+
+ override fun setMainProject(project: Project?) {
+ if (project != null && !openProjects.contains(project)) {
+ throw IllegalArgumentException("Project ${ProjectUtils.getInformation(project).displayName} is not open and cannot be set as main.")
+ }
+ mainProject = project
+ }
+
+ override fun openProjectsAPI() = null
+
+
+ override fun getActiveProjectGroupAPI() = null
+
+ override fun addProjectGroupChangeListenerAPI(pl: ProjectGroupChangeListener?) {}
+
+ override fun removeProjectGroupChangeListenerAPI(pl: ProjectGroupChangeListener?) {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/MockParser.kt b/contrib/kotlin/src/test/java/javaproject/mockservices/MockParser.kt
new file mode 100644
index 0000000..983ba4f
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/MockParser.kt
@@ -0,0 +1,22 @@
+package javaproject.mockservices
+
+import javax.swing.event.ChangeListener
+import org.netbeans.modules.parsing.api.Snapshot
+import org.netbeans.modules.parsing.api.Task
+import org.netbeans.modules.parsing.spi.ParseException
+import org.netbeans.modules.parsing.spi.Parser
+import org.netbeans.modules.parsing.spi.SourceModificationEvent
+
+class MockParser : Parser() {
+ override fun parse(snapshot: Snapshot?, task: Task?, event: SourceModificationEvent?) {}
+
+ override fun getResult(task: Task?) = object : Result(null) {
+ override fun invalidate() {}
+ }
+
+ override fun addChangeListener(changeListener: ChangeListener?) {
+ }
+
+ override fun removeChangeListener(changeListener: ChangeListener?) {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/MockParserFactory.java b/contrib/kotlin/src/test/java/javaproject/mockservices/MockParserFactory.java
new file mode 100644
index 0000000..30b11c9
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/MockParserFactory.java
@@ -0,0 +1,40 @@
+/**
+ * *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+package javaproject.mockservices;
+
+import java.util.Collection;
+import org.netbeans.api.editor.mimelookup.MimeRegistration;
+import org.netbeans.modules.java.source.parsing.JavacParserFactory;
+import org.netbeans.modules.parsing.api.Snapshot;
+import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.modules.parsing.spi.ParserFactory;
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+@MimeRegistration(mimeType = "text/x-java", service = ParserFactory.class)
+public class MockParserFactory extends ParserFactory {
+
+ @Override
+ public Parser createParser(Collection<Snapshot> snapshots) {
+ return new JavacParserFactory().createParser(snapshots);
+ }
+
+}
diff --git a/contrib/kotlin/src/test/java/javaproject/mockservices/TestEnvironmentFactory.java b/contrib/kotlin/src/test/java/javaproject/mockservices/TestEnvironmentFactory.java
new file mode 100644
index 0000000..5c58be3
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javaproject/mockservices/TestEnvironmentFactory.java
@@ -0,0 +1,121 @@
+package javaproject.mockservices;
+
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import javax.swing.text.Document;
+import org.netbeans.modules.java.source.parsing.JavacParserFactory;
+import org.netbeans.modules.masterfs.providers.ProvidedExtensions;
+import org.netbeans.modules.parsing.api.Snapshot;
+import org.netbeans.modules.parsing.api.Source;
+import org.netbeans.modules.parsing.implspi.EnvironmentFactory;
+import org.netbeans.modules.parsing.implspi.SchedulerControl;
+import org.netbeans.modules.parsing.implspi.SourceControl;
+import org.netbeans.modules.parsing.implspi.SourceEnvironment;
+import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.modules.parsing.spi.ParserFactory;
+import org.netbeans.modules.parsing.spi.Scheduler;
+import org.openide.cookies.EditorCookie;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * Simplified testing environment. Does not react on document changes or
+ * EditorRegistry changes.
+ *
+ * @author sdedic
+ */
+@ServiceProvider(service = EnvironmentFactory.class, position = 50000)
+public class TestEnvironmentFactory implements EnvironmentFactory {
+ private static final Map<String,Reference<Parser>> cachedParsers = new HashMap<String,Reference<Parser>>();
+
+ @Override
+ public Class<? extends Scheduler> findStandardScheduler(String schedulerName) {
+ return null;
+ }
+
+ @Override
+ public SourceEnvironment createEnvironment(Source src, SourceControl control) {
+ return new Env(control);
+ }
+
+ @Override
+ public <T> T runPriorityIO(Callable<T> r) throws Exception {
+ assert r != null;
+ return ProvidedExtensions.priorityIO(r);
+ }
+
+ @Override
+ public Lookup getContextLookup() {
+ return Lookup.getDefault();
+ }
+
+ @Override
+ public synchronized Parser findMimeParser(Lookup context, String mimeType) {
+ Reference<Parser> rp = cachedParsers.get(mimeType);
+ Parser p = null;
+ if (rp != null) {
+ p = rp.get();
+ }
+ if (p != null) {
+ return p;
+ }
+
+ ParserFactory f = new JavacParserFactory();
+ if (f != null) {
+ p = f.createParser(Collections.<Snapshot>emptyList());
+ } else {
+ p = new MockParser();
+ }
+ cachedParsers.put(mimeType, new WeakReference(p));
+ return p;
+ }
+
+ @Override
+ public Collection<? extends Scheduler> getSchedulers(Lookup context) {
+ return getContextLookup().lookupAll(Scheduler.class);
+ }
+
+
+ static class Env extends SourceEnvironment {
+
+ public Env(SourceControl ctrl) {
+ super(ctrl);
+ }
+
+ @Override
+ public boolean isReparseBlocked() {
+ return false;
+ }
+
+ @Override
+ public Document readDocument(FileObject f, boolean forceOpen) throws IOException {
+ DataObject d = DataObject.find(f);
+ EditorCookie cake = d.getLookup().lookup(EditorCookie.class);
+ if (!forceOpen) {
+ return cake.getDocument();
+ } else {
+ return cake.openDocument();
+ }
+ }
+
+ @Override
+ public void attachScheduler(SchedulerControl s, boolean attach) {
+ // FIXME - schedulers will not react if the source file changes
+ // because of rename etc.
+ }
+
+ @Override
+ public void activate() {
+ listenOnFileChanges();
+ listenOnParser();
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/javastubgen/JavaStubGeneratorTest.kt b/contrib/kotlin/src/test/java/javastubgen/JavaStubGeneratorTest.kt
new file mode 100644
index 0000000..0ad75e4
--- /dev/null
+++ b/contrib/kotlin/src/test/java/javastubgen/JavaStubGeneratorTest.kt
@@ -0,0 +1,80 @@
+/** *****************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package javastubgen
+
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.filesystem.JavaStubGenerator
+import org.jetbrains.kotlin.filesystem.lightclasses.KotlinLightClassGeneration
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.openide.filesystems.FileObject
+import utils.*
+
+class JavaStubGeneratorTest : KotlinTestCase("Stub generator test", "stubGen") {
+
+ private fun getByteCode(file: FileObject): List<ByteArray> {
+ val ktFile = KotlinPsiManager.getParsedFile(file)!!
+ val result = KotlinAnalyzer.analyzeFile(project, ktFile)
+
+ return KotlinLightClassGeneration.getByteCode(file, project, result.analysisResult)
+ }
+
+ private fun doTest(fileName: String, vararg after: String) {
+ val kotlinFile = dir.getFileObject("$fileName.kt")
+ val list = JavaStubGenerator.gen(getByteCode(kotlinFile))
+ if (after.isEmpty()) {
+ val expected = dir.getFileObject("$fileName.after").asText()
+ assertTrue(list.first().second equalsWithoutSpaces expected)
+ } else after.forEachIndexed { i, _ ->
+ val expected = dir.getFileObject("${after[i]}.after").asText()
+ assertTrue(list[i].second equalsWithoutSpaces expected)
+ }
+ }
+
+ fun testSimple() = doTest("simple")
+
+ fun testInterface() = doTest("interface")
+
+ fun testAbstractClass() = doTest("abstractClass")
+
+ fun testOpenClass() = doTest("openClass")
+
+ fun testEnum() = doTest("enum")
+
+ fun testClassWithTypeParameter() = doTest("classWithTypeParameter")
+
+// fun testWithoutClass() = doTest("withoutClass")
+
+ fun testObject() = doTest("object")
+
+ fun testClassWithVal() = doTest("classWithVal")
+
+ fun testClassWithVar() = doTest("classWithVar")
+
+ fun testSeveralClassesInOneFile() = doTest("severalClassesInOneFile", "FirstClass", "SecondClass")
+
+ fun testWithNestedClass() = doTest("withNestedClass")
+
+ fun testWithCompanion() = doTest("withCompanion")
+
+ fun testClassWithSeveralMethods() = doTest("withSeveralMethods")
+
+ fun testClassImplementsInterface() = doTest("implementsInterface", "implementsInterface2", "implementsInterface1")
+
+ fun testFunWithSeveralArguments() = doTest("severalArguments")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/navigation/NavigationTest.kt b/contrib/kotlin/src/test/java/navigation/NavigationTest.kt
new file mode 100644
index 0000000..71fcc53
--- /dev/null
+++ b/contrib/kotlin/src/test/java/navigation/NavigationTest.kt
@@ -0,0 +1,48 @@
+package navigation
+
+import javaproject.JavaProject
+import javax.swing.text.Document
+import org.jetbrains.kotlin.navigation.netbeans.KotlinHyperlinkProvider
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.netbeans.api.project.Project
+import org.netbeans.lib.editor.hyperlink.spi.HyperlinkType
+import org.openide.filesystems.FileObject
+import utils.*
+
+/**
+ *
+ * @author Alexander.Baratynski
+ */
+class NavigationTest : KotlinTestCase("Navigation test", "navigation") {
+ private val hyperlinkProvider = KotlinHyperlinkProvider()
+
+ private fun doTest(fromName: String, toName: String = fromName) {
+ val from = getDocumentForFileObject(dir, fromName)
+ assertNotNull(from)
+ val caret = getCaret(from)
+ assertNotNull(caret)
+ val offset = caret + "<caret>".length + 1
+
+ hyperlinkProvider.isHyperlinkPoint(from, offset, HyperlinkType.GO_TO_DECLARATION)
+ hyperlinkProvider.performClickAction(from, offset, HyperlinkType.GO_TO_DECLARATION)
+ val navigationData = hyperlinkProvider.navigationCache
+ assertNotNull(navigationData)
+
+ val to = navigationData.first
+ val toFO = ProjectUtils.getFileObjectForDocument(to)
+ assertNotNull(toFO)
+
+ val expectedFO = dir.getFileObject(toName)
+ assertEquals(expectedFO.path, toFO.path)
+
+ val expectedOffset = getCaret(getDocumentForFileObject(dir, toName.replace(".kt", ".caret")))
+ assertEquals(expectedOffset, navigationData.second)
+ }
+
+ fun tstNavigationToFunction() = doTest("checkNavigationToFunction.kt", "functionToNavigate.kt")
+
+ fun tstNavigationToClass() = doTest("checkNavigationToClass.kt", "KotlinClass.kt")
+
+ fun tstNavigationToVariable() = doTest("checkNavigationToVariable.kt")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/quickfixes/QuickFixesTest.kt b/contrib/kotlin/src/test/java/quickfixes/QuickFixesTest.kt
new file mode 100644
index 0000000..89fac25
--- /dev/null
+++ b/contrib/kotlin/src/test/java/quickfixes/QuickFixesTest.kt
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package quickfixes
+
+import org.openide.filesystems.FileObject
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.diagnostics.netbeans.parser.*
+import org.jetbrains.kotlin.hints.fixes.*
+import org.jetbrains.kotlin.utils.ProjectUtils
+import utils.*
+
+class QuickFixesTest : KotlinTestCase("Quick Fixes test", "quickfixes") {
+
+ private fun doTest(fileName: String, fix: Class<out KotlinQuickFix>) {
+ val doc = getDocumentForFileObject(dir, "$fileName.kt")
+ val file = dir.getFileObject("$fileName.kt")
+ val ktFile = KotlinPsiManager.getParsedFile(file)!!
+ val project = ProjectUtils.getKotlinProjectForFileObject(file)
+
+ val resultWithProvider = KotlinParser.getAnalysisResult(ktFile, project)!!
+ val parserResult = KotlinParserResult(null, resultWithProvider, ktFile, file, project)
+
+ val error = parserResult.getDiagnostics().first()
+ val quickFix = fix.constructors.first().newInstance(error, parserResult) as KotlinQuickFix
+
+ assertTrue(quickFix.isApplicable())
+
+ quickFix.implement()
+ assertTrue(doc.getText(0, doc.length) equalsWithoutSpaces dir.getFileObject("$fileName.after").asText())
+ }
+
+ fun testRemoveUnnecessarySafeCall() = doTest("removeUnnecessaryCall", RemoveUnnecessarySafeCallFix::class.java)
+
+ fun testRemoveUselessCastFix() = doTest("removeUselessCast", RemoveUselessCastFix::class.java)
+
+ fun testRemoveUselessElvisFix() = doTest("removeUselessElvis", RemoveUselessElvisFix::class.java)
+
+ fun testImplementMembersFix() = doTest("implementMembers", ImplementMembersFix::class.java)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/rename/RenameTest.kt b/contrib/kotlin/src/test/java/rename/RenameTest.kt
new file mode 100644
index 0000000..a62a240
--- /dev/null
+++ b/contrib/kotlin/src/test/java/rename/RenameTest.kt
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package rename
+
+import com.intellij.psi.PsiElement
+import javaproject.JavaProject
+import javax.swing.text.Document
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.refactorings.rename.transaction
+import org.jetbrains.kotlin.refactorings.rename.getRenameRefactoringMap
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.OffsetRange
+import org.netbeans.modules.refactoring.spi.Transaction
+import org.openide.filesystems.FileObject
+import utils.*
+
+class RenameTest : KotlinTestCase("Rename Test", "rename") {
+
+ private fun doRefactoring(newName: String, fo: FileObject, psi: PsiElement) {
+ val renameMap = getRenameRefactoringMap(fo, psi, newName)
+ transaction(renameMap).commit()
+ }
+
+ private fun checkTextsEquality(actual: FileObject, supposed: FileObject) {
+ val beforeDoc = getDocumentForFileObject(actual)
+ val afterDoc = getDocumentForFileObject(supposed)
+
+ val actualText = beforeDoc.getText(0, beforeDoc.length)
+ val supposedText = afterDoc.getText(0, afterDoc.length)
+
+ assertNotNull(actualText)
+ assertNotNull(supposedText)
+
+ assertEquals(supposedText, actualText)
+ }
+
+ private fun doTest(pack: String, name: String, newName: String) {
+ val packFile = dir.getFileObject(pack)
+ val before = packFile.getFileObject("$name.kt")
+ val beforeWithCaret = packFile.getFileObject("$name.caret")
+
+ val caretOffset = getCaret(getDocumentForFileObject(beforeWithCaret))
+ assertNotNull(caretOffset)
+
+ val ktFile = KotlinPsiManager.getParsedFile(before)
+ assertNotNull(ktFile)
+
+ val psi = ktFile!!.findElementAt(caretOffset)
+ assertNotNull(psi)
+
+ doRefactoring(newName, before, psi!!)
+
+ for (file in getAllKtFilesInFolder(packFile)) {
+ val fileName = file.name
+ val afterFile = packFile.getFileObject("$fileName.after")
+ assertNotNull(afterFile)
+
+ checkTextsEquality(file, afterFile)
+ }
+ }
+
+ fun testSimpleCase() = doTest("simple", "file", "NewName")
+
+ fun testSecondSimpleCase() = doTest("properties", "file", "someValue")
+
+ fun testThirdSimpleCase() = doTest("simplesec", "file", "someValue")
+
+ fun testFunctionParameterRenaming() = doTest("functionparameter", "file", "someValue")
+
+ fun testFunctionRenaming() = doTest("function", "file", "fooFunc")
+
+ fun testClassRenaming() = doTest("classrename", "file", "NewName")
+
+ fun testMethodRenaming() = doTest("methodrename", "file", "notSoCoolFun")
+
+ fun testForLoop() = doTest("forloop", "file", "arg1")
+
+ fun testForLoop2() = doTest("forloop2", "file", "arg1")
+
+ fun testRenameKotlinClassByConstructorRef() = doTest("classbyconstructor", "file", "KotlinRules")
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/semantic/SemanticAnalyzerTest.kt b/contrib/kotlin/src/test/java/semantic/SemanticAnalyzerTest.kt
new file mode 100644
index 0000000..d0d5a5b
--- /dev/null
+++ b/contrib/kotlin/src/test/java/semantic/SemanticAnalyzerTest.kt
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package semantic
+
+import javaproject.JavaProject
+import javax.swing.text.Document
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.ColoringAttributes
+import org.netbeans.modules.csl.api.OffsetRange
+import org.openide.filesystems.FileObject
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.highlighter.semanticanalyzer.*
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.resolve.AnalysisResultWithProvider
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.utils.ProjectUtils
+import utils.*
+
+typealias Attr = KotlinHighlightingAttributes
+
+class SemanticAnalyzerTest : KotlinTestCase("SemanticAnalyzer test", "semantic") {
+ private infix fun Int.to(end: Int) = OffsetRange(this, end)
+
+ private fun List<Int>.toOffsetRanges(): List<OffsetRange> {
+ val ranges = arrayListOf<OffsetRange>()
+
+ var i = 0
+ while (i < size - 1) {
+ ranges.add(this[i] to this[i + 1])
+ i += 2
+ }
+
+ return ranges
+ }
+
+ private fun attrs(fileName: String, attrs: List<Attr>, withSmartCast: Boolean = false): Map<OffsetRange, Set<ColoringAttributes>> {
+ val doc = getDocumentForFileObject(dir, "$fileName.caret")
+ val ranges = doc.carets().toOffsetRanges()
+
+ return hashMapOf<OffsetRange, Set<ColoringAttributes>>().apply {
+ attrs.forEachIndexed { i, it ->
+ put(ranges[i], it.styleKey.let {
+ if (withSmartCast) it.toMutableSet().apply { addAll(Attr.SMART_CAST.styleKey) } else it
+ })
+ }
+ }
+ }
+
+ private fun doTest(fileName: String, vararg attrs: Attr, withSmartCast: Boolean = false) {
+ val file = dir.getFileObject("$fileName.kt")
+ val ktFile = KotlinPsiManager.getParsedFile(file)!!
+
+ val resultWithProvider = KotlinAnalyzer.analyzeFile(project, ktFile)
+
+ val highlights = KotlinSemanticAnalyzer().let {
+ it.highlight(resultWithProvider.analysisResult, ktFile)
+ it.highlights
+ }
+
+ assertTrue(highlights.entries.containsAll(attrs(fileName, attrs.toList(), withSmartCast).entries))
+ }
+
+ fun testEmpty() = doTest("empty")
+
+ fun testSimpleClass() = doTest("simpleClass", Attr.CLASS)
+
+ fun testClass() = doTest("class", Attr.CLASS, Attr.FINAL_FIELD)
+
+ fun testFunctionWithLocalVariables() = doTest("functionWithLocalVariables", Attr.FUNCTION_DECLARATION,
+ Attr.LOCAL_FINAL_VARIABLE, Attr.LOCAL_VARIABLE)
+
+ fun testAnnotation() = doTest("annotation", Attr.ANNOTATION)
+
+ fun testDeprecated() = doTest("deprecated", Attr.DEPRECATED)
+
+ fun testSmartCast() = doTest("smartCast", Attr.LOCAL_FINAL_VARIABLE, withSmartCast = true)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/structurescanner/FoldingTest.kt b/contrib/kotlin/src/test/java/structurescanner/FoldingTest.kt
new file mode 100644
index 0000000..02c509b
--- /dev/null
+++ b/contrib/kotlin/src/test/java/structurescanner/FoldingTest.kt
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package structurescanner
+
+import javaproject.JavaProject
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.structurescanner.*
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.StructureItem
+import org.openide.filesystems.FileObject
+import utils.KotlinTestCase
+
+class FoldingTest : KotlinTestCase("Folding test", "folding") {
+
+ private fun doTest(fileName: String, codeBlocks: Int = 0, comments: Int = 0) {
+ val file = dir.getFileObject("$fileName.kt")
+ assertNotNull(file)
+
+ val folds = KotlinStructureScanner().foldMap(file)
+
+ assertEquals(codeBlocks, folds["codeblocks"]?.size)
+ assertEquals(comments, folds["comments"]?.size)
+ }
+
+ fun testLicenseHeader() = doTest("licenseHeader", comments = 1)
+
+ fun testFunction() = doTest("function", codeBlocks = 1)
+
+ fun testFunctionWithBody() = doTest("functionWithBody", codeBlocks = 2)
+
+ fun testClass() = doTest("class", codeBlocks = 6, comments = 2)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/structurescanner/StructureScannerTest.kt b/contrib/kotlin/src/test/java/structurescanner/StructureScannerTest.kt
new file mode 100644
index 0000000..3790c27
--- /dev/null
+++ b/contrib/kotlin/src/test/java/structurescanner/StructureScannerTest.kt
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package structurescanner
+
+import javaproject.JavaProject
+import org.jetbrains.kotlin.builder.KotlinPsiManager
+import org.jetbrains.kotlin.resolve.KotlinAnalyzer
+import org.jetbrains.kotlin.structurescanner.*
+import org.netbeans.api.project.Project
+import org.netbeans.modules.csl.api.StructureItem
+import org.openide.filesystems.FileObject
+import utils.KotlinTestCase
+
+class StructureScannerTest : KotlinTestCase("StructureScanner test", "structureScanner") {
+
+ private val StructureItem.allItems: List<StructureItem>
+ get() = arrayListOf(this).apply { addAll(nestedItems.flatMap { it.allItems }) }
+
+ private fun doTest(fileName: String, functions: Int = 0, properties: Int = 0, classes: Int = 0) {
+ val file = dir.getFileObject("$fileName.kt")
+ assertNotNull(file)
+
+ val ktFile = KotlinPsiManager.getParsedFile(file)!!
+ val resultWithProvider = KotlinAnalyzer.analyzeFile(project, ktFile)
+
+ val items = KotlinStructureScanner().structureItems(file, resultWithProvider.analysisResult.bindingContext)
+ .flatMap { it.allItems }
+
+ assertEquals(functions, items.filterIsInstance<KotlinFunctionStructureItem>().size)
+ assertEquals(properties, items.filterIsInstance<KotlinPropertyStructureItem>().size)
+ assertEquals(classes, items.filterIsInstance<KotlinClassStructureItem>().size)
+ }
+
+ fun testEmpty() = doTest("empty")
+
+ fun testSimple() = doTest("simple", functions = 1)
+
+ fun testSeveralFunctions() = doTest("severalFunctions", functions = 2)
+
+ fun testObject() = doTest("object", classes = 1, functions = 1)
+
+ fun testClassWithSeveralMembers() = doTest("classWithSeveralMembers", classes = 2, functions = 1, properties = 1)
+
+ fun testSeveralClasses() = doTest("severalClasses", classes = 4, functions = 3, properties = 3)
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/utils/KotlinTestCase.kt b/contrib/kotlin/src/test/java/utils/KotlinTestCase.kt
new file mode 100644
index 0000000..7eeedeb
--- /dev/null
+++ b/contrib/kotlin/src/test/java/utils/KotlinTestCase.kt
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package utils
+
+import javaproject.JavaProject
+import org.netbeans.api.project.Project
+import org.netbeans.junit.NbTestCase
+import org.openide.filesystems.FileObject
+
+abstract class KotlinTestCase(name: String, dirName: String) : NbTestCase(name) {
+
+ val project: Project
+ val dir: FileObject
+
+ init {
+ project = JavaProject.javaProject
+ dir = project.projectDirectory.getFileObject("src").getFileObject(dirName)
+ }
+
+ fun testProjectCreation() {
+ assertNotNull(project)
+ assertNotNull(dir)
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/java/utils/testUtils.kt b/contrib/kotlin/src/test/java/utils/testUtils.kt
new file mode 100644
index 0000000..ece1caf
--- /dev/null
+++ b/contrib/kotlin/src/test/java/utils/testUtils.kt
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
+package utils
+
+import com.intellij.openapi.util.text.StringUtil
+import javax.swing.text.Document
+import junit.framework.TestCase.assertNotNull
+import org.jetbrains.kotlin.utils.ProjectUtils
+import org.openide.filesystems.FileObject
+
+fun getCaret(doc: Document): Int = doc.getText(0,doc.length).indexOf("<caret>")
+
+fun Document.carets(): List<Int> {
+ val result = arrayListOf<Int>()
+ val caret = "<caret>"
+ val text = getText(0, length)
+
+ var index = 0
+
+ while(true) {
+ val newIndex = text.substring(index).indexOf(caret)
+ if (newIndex == -1) break
+
+ index += newIndex
+ result.add(index)
+
+ index += caret.length
+ }
+
+ return result.mapIndexed { i, it -> it - caret.length * i}
+}
+
+fun getDocumentForFileObject(fo: FileObject) = ProjectUtils.getDocumentFromFileObject(fo)
+
+fun getDocumentForFileObject(dir: FileObject, fileName: String): Document {
+ val file = dir.getFileObject(fileName)
+
+ assertNotNull(file)
+
+ return getDocumentForFileObject(file)
+}
+
+fun getAllKtFilesInFolder(folder: FileObject) = folder.children.filter{ it.hasExt("kt") }
+
+infix fun String.equalsWithoutSpaces(expected: String): Boolean {
+ val spacesRegex = Regex("\\s+")
+
+ return spacesRegex.replace(StringUtil.convertLineSeparators(expected), "") ==
+ spacesRegex.replace(StringUtil.convertLineSeparators(this), "")
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/build.xml b/contrib/kotlin/src/test/resources/projForTest/build.xml
new file mode 100644
index 0000000..14317bb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/build.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="projForTest" default="default" basedir=".">
+ <description>Builds, tests, and runs the project projForTest.</description>
+ <import file="nbproject/build-impl.xml"/>
+ <!--
+
+ There exist several targets which are by default empty and which can be
+ used for execution of your tasks. These targets are usually executed
+ before and after some main targets. They are:
+
+ -pre-init: called before initialization of project properties
+ -post-init: called after initialization of project properties
+ -pre-compile: called before javac compilation
+ -post-compile: called after javac compilation
+ -pre-compile-single: called before javac compilation of single file
+ -post-compile-single: called after javac compilation of single file
+ -pre-compile-test: called before javac compilation of JUnit tests
+ -post-compile-test: called after javac compilation of JUnit tests
+ -pre-compile-test-single: called before javac compilation of single JUnit test
+ -post-compile-test-single: called after javac compilation of single JUunit test
+ -pre-jar: called before JAR building
+ -post-jar: called after JAR building
+ -post-clean: called after cleaning build products
+
+ (Targets beginning with '-' are not intended to be called on their own.)
+
+ Example of inserting an obfuscator after compilation could look like this:
+
+ <target name="-post-compile">
+ <obfuscate>
+ <fileset dir="${build.classes.dir}"/>
+ </obfuscate>
+ </target>
+
+ For list of available properties check the imported
+ nbproject/build-impl.xml file.
+
+
+ Another way to customize the build is by overriding existing main targets.
+ The targets of interest are:
+
+ -init-macrodef-javac: defines macro for javac compilation
+ -init-macrodef-junit: defines macro for junit execution
+ -init-macrodef-debug: defines macro for class debugging
+ -init-macrodef-java: defines macro for class execution
+ -do-jar: JAR building
+ run: execution of project
+ -javadoc-build: Javadoc generation
+ test-report: JUnit report generation
+
+ An example of overriding the target for project execution could look like this:
+
+ <target name="run" depends="projForTest-impl.jar">
+ <exec dir="bin" executable="launcher.exe">
+ <arg file="${dist.jar}"/>
+ </exec>
+ </target>
+
+ Notice that the overridden target depends on the jar target and not only on
+ the compile target as the regular run target does. Again, for a list of available
+ properties which you can use, check the target you are overriding in the
+ nbproject/build-impl.xml file.
+
+ -->
+</project>
diff --git a/contrib/kotlin/src/test/resources/projForTest/manifest.mf b/contrib/kotlin/src/test/resources/projForTest/manifest.mf
new file mode 100644
index 0000000..328e8e5
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/contrib/kotlin/src/test/resources/projForTest/nbproject/build-impl.xml b/contrib/kotlin/src/test/resources/projForTest/nbproject/build-impl.xml
new file mode 100644
index 0000000..582662e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/nbproject/build-impl.xml
@@ -0,0 +1,1423 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+ - initialization
+ - compilation
+ - jar
+ - execution
+ - debugging
+ - javadoc
+ - test compilation
+ - test execution
+ - test debugging
+ - applet
+ - cleanup
+
+ -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="projForTest-impl">
+ <property name="kotlin.lib" value="C:\Kotlin\kotlinc\lib"/>
+ <typedef classpath="${kotlin.lib}/kotlin-ant.jar" resource="org/jetbrains/kotlin/ant/antlib.xml"/>
+ <fail message="Please build using Ant 1.8.0 or higher.">
+ <condition>
+ <not>
+ <antversion atleast="1.8.0"/>
+ </not>
+ </condition>
+ </fail>
+ <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+ <!--
+ ======================
+ INITIALIZATION SECTION
+ ======================
+ -->
+ <target name="-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init" name="-init-private">
+ <property file="nbproject/private/config.properties"/>
+ <property file="nbproject/private/configs/${config}.properties"/>
+ <property file="nbproject/private/private.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private" name="-init-user">
+ <property file="${user.properties.file}"/>
+ <!-- The two properties below are usually overridden -->
+ <!-- by the active platform. Just a fallback. -->
+ <property name="default.javac.source" value="1.4"/>
+ <property name="default.javac.target" value="1.4"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+ <property file="nbproject/configs/${config}.properties"/>
+ <property file="nbproject/project.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+ <property name="platform.java" value="${java.home}/bin/java"/>
+ <available file="${manifest.file}" property="manifest.available"/>
+ <condition property="splashscreen.available">
+ <and>
+ <not>
+ <equals arg1="${application.splash}" arg2="" trim="true"/>
+ </not>
+ <available file="${application.splash}"/>
+ </and>
+ </condition>
+ <condition property="main.class.available">
+ <and>
+ <isset property="main.class"/>
+ <not>
+ <equals arg1="${main.class}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="profile.available">
+ <and>
+ <isset property="javac.profile"/>
+ <length length="0" string="${javac.profile}" when="greater"/>
+ <matches pattern="1\.[89](\..*)?" string="${javac.source}"/>
+ </and>
+ </condition>
+ <condition property="do.archive">
+ <or>
+ <not>
+ <istrue value="${jar.archive.disabled}"/>
+ </not>
+ <istrue value="${not.archive.disabled}"/>
+ </or>
+ </condition>
+ <condition property="do.mkdist">
+ <and>
+ <isset property="do.archive"/>
+ <isset property="libs.CopyLibs.classpath"/>
+ <not>
+ <istrue value="${mkdist.disabled}"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="do.archive+manifest.available">
+ <and>
+ <isset property="manifest.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+main.class.available">
+ <and>
+ <isset property="main.class.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+splashscreen.available">
+ <and>
+ <isset property="splashscreen.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="do.archive+profile.available">
+ <and>
+ <isset property="profile.available"/>
+ <istrue value="${do.archive}"/>
+ </and>
+ </condition>
+ <condition property="have.tests">
+ <or>
+ <available file="${test.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="have.sources">
+ <or>
+ <available file="${src.dir}"/>
+ </or>
+ </condition>
+ <condition property="netbeans.home+have.tests">
+ <and>
+ <isset property="netbeans.home"/>
+ <isset property="have.tests"/>
+ </and>
+ </condition>
+ <condition property="no.javadoc.preview">
+ <and>
+ <isset property="javadoc.preview"/>
+ <isfalse value="${javadoc.preview}"/>
+ </and>
+ </condition>
+ <property name="run.jvmargs" value=""/>
+ <property name="run.jvmargs.ide" value=""/>
+ <property name="javac.compilerargs" value=""/>
+ <property name="work.dir" value="${basedir}"/>
+ <condition property="no.deps">
+ <and>
+ <istrue value="${no.dependencies}"/>
+ </and>
+ </condition>
+ <property name="javac.debug" value="true"/>
+ <property name="javadoc.preview" value="true"/>
+ <property name="application.args" value=""/>
+ <property name="source.encoding" value="${file.encoding}"/>
+ <property name="runtime.encoding" value="${source.encoding}"/>
+ <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+ <and>
+ <isset property="javadoc.encoding"/>
+ <not>
+ <equals arg1="${javadoc.encoding}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <property name="javadoc.encoding.used" value="${source.encoding}"/>
+ <property name="includes" value="**"/>
+ <property name="excludes" value=""/>
+ <property name="do.depend" value="false"/>
+ <condition property="do.depend.true">
+ <istrue value="${do.depend}"/>
+ </condition>
+ <path id="endorsed.classpath.path" path="${endorsed.classpath}"/>
+ <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'">
+ <and>
+ <isset property="endorsed.classpath"/>
+ <not>
+ <equals arg1="${endorsed.classpath}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition else="" property="javac.profile.cmd.line.arg" value="-profile ${javac.profile}">
+ <isset property="profile.available"/>
+ </condition>
+ <condition else="false" property="jdkBug6558476">
+ <and>
+ <matches pattern="1\.[56]" string="${java.specification.version}"/>
+ <not>
+ <os family="unix"/>
+ </not>
+ </and>
+ </condition>
+ <condition else="false" property="javac.fork">
+ <or>
+ <istrue value="${jdkBug6558476}"/>
+ <istrue value="${javac.external.vm}"/>
+ </or>
+ </condition>
+ <property name="jar.index" value="false"/>
+ <property name="jar.index.metainf" value="${jar.index}"/>
+ <property name="copylibs.rebase" value="true"/>
+ <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/>
+ <condition property="junit.available">
+ <or>
+ <available classname="org.junit.Test" classpath="${run.test.classpath}"/>
+ <available classname="junit.framework.Test" classpath="${run.test.classpath}"/>
+ </or>
+ </condition>
+ <condition property="testng.available">
+ <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/>
+ </condition>
+ <condition property="junit+testng.available">
+ <and>
+ <istrue value="${junit.available}"/>
+ <istrue value="${testng.available}"/>
+ </and>
+ </condition>
+ <condition else="testng" property="testng.mode" value="mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ <condition else="" property="testng.debug.mode" value="-mixed">
+ <istrue value="${junit+testng.available}"/>
+ </condition>
+ <property name="java.failonerror" value="true"/>
+ </target>
+ <target name="-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+ <fail unless="src.dir">Must set src.dir</fail>
+ <fail unless="test.src.dir">Must set test.src.dir</fail>
+ <fail unless="build.dir">Must set build.dir</fail>
+ <fail unless="dist.dir">Must set dist.dir</fail>
+ <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+ <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+ <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+ <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+ <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+ <fail unless="dist.jar">Must set dist.jar</fail>
+ </target>
+ <target name="-init-macrodef-property">
+ <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${@{value}}"/>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <mkdir dir="@{apgeneratedsrcdir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <withKotlin/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.profile.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <compilerarg value="-processorpath"/>
+ <compilerarg path="@{processorpath}:${empty.dir}"/>
+ <compilerarg line="${ap.processors.internal}"/>
+ <compilerarg line="${annotation.processing.processor.options}"/>
+ <compilerarg value="-s"/>
+ <compilerarg path="@{apgeneratedsrcdir}"/>
+ <compilerarg line="${ap.proc.none.internal}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${javac.processorpath}" name="processorpath"/>
+ <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="${empty.dir}" name="sourcepath"/>
+ <attribute default="${empty.dir}" name="gensrcdir"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.dir}/empty" name="empty.dir"/>
+ <mkdir dir="${empty.dir}"/>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}">
+ <src>
+ <dirset dir="@{gensrcdir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </src>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <compilerarg line="${javac.profile.cmd.line.arg}"/>
+ <compilerarg line="${javac.compilerargs}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
+ <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <sequential>
+ <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </depend>
+ </sequential>
+ </macrodef>
+ <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <sequential>
+ <fail unless="javac.includes">Must set javac.includes</fail>
+ <pathconvert pathsep="${line.separator}" property="javac.includes.binary">
+ <path>
+ <filelist dir="@{destdir}" files="${javac.includes}"/>
+ </path>
+ <globmapper from="*.java" to="*.class"/>
+ </pathconvert>
+ <tempfile deleteonexit="true" property="javac.includesfile.binary"/>
+ <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/>
+ <delete>
+ <files includesfile="${javac.includesfile.binary}"/>
+ </delete>
+ <delete>
+ <fileset file="${javac.includesfile.binary}"/>
+ </delete>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-init">
+ <condition else="false" property="nb.junit.batch" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <not>
+ <isset property="test.method"/>
+ </not>
+ </and>
+ </condition>
+ <condition else="false" property="nb.junit.single" value="true">
+ <and>
+ <istrue value="${junit.available}"/>
+ <isset property="test.method"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-init-test-properties">
+ <property name="test.binaryincludes" value="<nothing>"/>
+ <property name="test.binarytestincludes" value=""/>
+ <property name="test.binaryexcludes" value=""/>
+ </target>
+ <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/>
+ <target if="${testng.available}" name="-init-macrodef-testng">
+ <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}">
+ <isset property="test.method"/>
+ </condition>
+ <union id="test.set">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ </union>
+ <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/>
+ <testng classfilesetref="test.set" failureProperty="tests.failed" listeners="org.testng.reporters.VerboseReporter" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="projForTest" testname="TestNG tests" workingDir="${work.dir}">
+ <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/>
+ <propertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </propertyset>
+ <customize/>
+ </testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-test-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <echo>No tests executed.</echo>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl">
+ <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:testng>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test">
+ <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <sequential>
+ <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-test-properties" if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch">
+ <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property name="junit.forkmode" value="perTest"/>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ <fileset dir="${build.test.classes.dir}" excludes="@{excludes},${excludes},${test.binaryexcludes}" includes="${test.binaryincludes}">
+ <filename name="${test.binarytestincludes}"/>
+ </fileset>
+ </batchtest>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg value="-ea"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <customize/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl">
+ <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <element implicit="true" name="customize" optional="true"/>
+ <sequential>
+ <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize/>
+ </j2seproject3:junit-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target if="${testng.available}" name="-init-macrodef-testng-debug">
+ <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element name="customize2" optional="true"/>
+ <sequential>
+ <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}">
+ <isset property="test.method"/>
+ </condition>
+ <condition else="-suitename projForTest -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}">
+ <matches pattern=".*\.xml" string="@{testClass}"/>
+ </condition>
+ <delete dir="${build.test.results.dir}" quiet="true"/>
+ <mkdir dir="${build.test.results.dir}"/>
+ <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}">
+ <customize>
+ <customize2/>
+ <jvmarg value="-ea"/>
+ <arg line="${testng.debug.mode}"/>
+ <arg line="-d ${build.test.results.dir}"/>
+ <arg line="-listener org.testng.reporters.VerboseReporter"/>
+ <arg line="${testng.cmd.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl">
+ <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <element implicit="true" name="customize2" optional="true"/>
+ <sequential>
+ <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2/>
+ </j2seproject3:testng-debug>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}">
+ <customize>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ </customize>
+ </j2seproject3:test-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng">
+ <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <attribute default="" name="testmethods"/>
+ <attribute default="${main.class}" name="testClass"/>
+ <attribute default="" name="testMethod"/>
+ <sequential>
+ <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}">
+ <customize2>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ </customize2>
+ </j2seproject3:testng-debug-impl>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/>
+ <!--
+ pre NB7.2 profiling section; consider it deprecated
+ -->
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/>
+ <target if="profiler.info.jvmargs.agent" name="-profile-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile">
+ <macrodef name="resolve">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${env.@{value}}"/>
+ </sequential>
+ </macrodef>
+ <macrodef name="profile">
+ <attribute default="${main.class}" name="classname"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property environment="env"/>
+ <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
+ <java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <arg line="${application.args}"/>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check">
+ <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail>
+ <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail>
+ </target>
+ <!--
+ end of pre NB7.2 profiling section
+ -->
+ <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+ <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="name"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <attribute default="" name="stopclassname"/>
+ <sequential>
+ <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </nbjpdastart>
+ </sequential>
+ </macrodef>
+ <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${build.classes.dir}" name="dir"/>
+ <sequential>
+ <nbjpdareload>
+ <fileset dir="@{dir}" includes="${fix.classes}">
+ <include name="${fix.includes}*.class"/>
+ </fileset>
+ </nbjpdareload>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-debug-args">
+ <property name="version-output" value="java version "${ant.java.version}"/>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-debug">
+ <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-java">
+ <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${run.classpath}" name="classpath"/>
+ <attribute default="jvm" name="jvm"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
+ <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
+ <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
+ <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <jvmarg line="${run.jvmargs.ide}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-copylibs">
+ <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${manifest.file}" name="manifest"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <filtermapper>
+ <replacestring from=" " to="%20"/>
+ </filtermapper>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" excludeFromCopy="${copylibs.excludes}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/>
+ <manifest>
+ <attribute name="Class-Path" value="${jar.classpath}"/>
+ <customize/>
+ </manifest>
+ </copylibs>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-presetdef-jar">
+ <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
+ <j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes}"/>
+ </jar>
+ </presetdef>
+ </target>
+ <target name="-init-ap-cmdline-properties">
+ <property name="annotation.processing.enabled" value="true"/>
+ <property name="annotation.processing.processors.list" value=""/>
+ <property name="annotation.processing.processor.options" value=""/>
+ <property name="annotation.processing.run.all.processors" value="true"/>
+ <property name="javac.processorpath" value="${javac.classpath}"/>
+ <property name="javac.test.processorpath" value="${javac.test.classpath}"/>
+ <condition property="ap.supported.internal" value="true">
+ <not>
+ <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/>
+ </not>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported">
+ <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}">
+ <isfalse value="${annotation.processing.run.all.processors}"/>
+ </condition>
+ <condition else="" property="ap.proc.none.internal" value="-proc:none">
+ <isfalse value="${annotation.processing.enabled}"/>
+ </condition>
+ </target>
+ <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline">
+ <property name="ap.cmd.line.internal" value=""/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/>
+ <!--
+ ===================
+ COMPILATION SECTION
+ ===================
+ -->
+ <target name="-deps-jar-init" unless="built-jar.properties">
+ <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/>
+ <delete file="${built-jar.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.jar.${basedir}" name="-warn-already-built-jar">
+ <echo level="warn" message="Cycle detected: projForTest was already built"/>
+ </target>
+ <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-jar.properties}" verbose="false"/>
+ <property file="${built-jar.properties}" prefix="already.built.jar."/>
+ <antcall target="-warn-already-built-jar"/>
+ <propertyfile file="${built-jar.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ </target>
+ <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+ <target depends="init" name="-check-automatic-build">
+ <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+ </target>
+ <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+ <antcall target="clean"/>
+ </target>
+ <target depends="init,deps-jar" name="-pre-pre-compile">
+ <mkdir dir="${build.classes.dir}"/>
+ </target>
+ <target name="-pre-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-depend">
+ <pathconvert property="build.generated.subdirs">
+ <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="*"/>
+ </dirset>
+ </pathconvert>
+ <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/>
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
+ <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
+ <copy todir="${build.classes.dir}">
+ <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target if="has.persistence.xml" name="-copy-persistence-xml">
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy todir="${build.classes.dir}/META-INF">
+ <fileset dir="${meta.inf.dir}" includes="persistence.xml orm.xml"/>
+ </copy>
+ </target>
+ <target name="-post-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+ <target name="-pre-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile/>
+ <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/>
+ </target>
+ <target name="-post-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+ <!--
+ ====================
+ JAR BUILDING SECTION
+ ====================
+ -->
+ <target depends="init" name="-pre-pre-jar">
+ <dirname file="${dist.jar}" property="dist.jar.dir"/>
+ <mkdir dir="${dist.jar.dir}"/>
+ </target>
+ <target name="-pre-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init" if="do.archive" name="-do-jar-create-manifest" unless="manifest.available">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <touch file="${tmp.manifest.file}" verbose="false"/>
+ </target>
+ <target depends="init" if="do.archive+manifest.available" name="-do-jar-copy-manifest">
+ <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/>
+ <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/>
+ </target>
+ <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+main.class.available" name="-do-jar-set-mainclass">
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="Main-Class" value="${main.class}"/>
+ </manifest>
+ </target>
+ <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+profile.available" name="-do-jar-set-profile">
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="Profile" value="${javac.profile}"/>
+ </manifest>
+ </target>
+ <target depends="init,-do-jar-create-manifest,-do-jar-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-set-splashscreen">
+ <basename file="${application.splash}" property="splashscreen.basename"/>
+ <mkdir dir="${build.classes.dir}/META-INF"/>
+ <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/>
+ <manifest file="${tmp.manifest.file}" mode="update">
+ <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/>
+ </manifest>
+ </target>
+ <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.mkdist" name="-do-jar-copylibs">
+ <j2seproject3:copylibs manifest="${tmp.manifest.file}"/>
+ <echo level="info">To run this application from the command line without Ant, try:</echo>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <echo level="info">java -jar "${dist.jar.resolved}"</echo>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen" if="do.archive" name="-do-jar-jar" unless="do.mkdist">
+ <j2seproject1:jar manifest="${tmp.manifest.file}"/>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <pathconvert property="run.classpath.with.dist.jar">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+ </pathconvert>
+ <condition else="" property="jar.usage.message" value="To run this application from the command line without Ant, try:${line.separator}${platform.java} -cp ${run.classpath.with.dist.jar} ${main.class}">
+ <isset property="main.class.available"/>
+ </condition>
+ <condition else="debug" property="jar.usage.level" value="info">
+ <isset property="main.class.available"/>
+ </condition>
+ <echo level="${jar.usage.level}" message="${jar.usage.message}"/>
+ </target>
+ <target depends="-do-jar-copylibs" if="do.archive" name="-do-jar-delete-manifest">
+ <delete>
+ <fileset file="${tmp.manifest.file}"/>
+ </delete>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-jar,-do-jar-delete-manifest" name="-do-jar-without-libraries"/>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-create-manifest,-do-jar-copy-manifest,-do-jar-set-mainclass,-do-jar-set-profile,-do-jar-set-splashscreen,-do-jar-copylibs,-do-jar-delete-manifest" name="-do-jar-with-libraries"/>
+ <target name="-post-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-jar,-do-jar-without-libraries,-do-jar-with-libraries,-post-jar" name="-do-jar"/>
+ <target depends="init,compile,-pre-jar,-do-jar,-post-jar" description="Build JAR." name="jar"/>
+ <!--
+ =================
+ EXECUTION SECTION
+ =================
+ -->
+ <target depends="init,compile" description="Run a main class." name="run">
+ <j2seproject1:java>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <target name="-do-not-recompile">
+ <property name="javac.includes.binary" value=""/>
+ </target>
+ <target depends="init,compile-single" name="run-single">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}"/>
+ </target>
+ <target depends="init,compile-test-single" name="run-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/>
+ </target>
+ <!--
+ =================
+ DEBUGGING SECTION
+ =================
+ -->
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+ <j2seproject1:nbjpdastart name="${debug.class}"/>
+ </target>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/>
+ </target>
+ <target depends="init,compile" name="-debug-start-debuggee">
+ <j2seproject3:debug>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+ <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+ </target>
+ <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}"/>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+ <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/>
+ <target depends="init" name="-pre-debug-fix">
+ <fail unless="fix.includes">Must set fix.includes</fail>
+ <property name="javac.includes" value="${fix.includes}.java"/>
+ </target>
+ <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+ <j2seproject1:nbjpdareload/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+ <!--
+ =================
+ PROFILING SECTION
+ =================
+ -->
+ <!--
+ pre NB7.2 profiler integration
+ -->
+ <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile/>
+ </target>
+ <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72">
+ <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail>
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="${profile.class}"/>
+ </target>
+ <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <profile classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </profile>
+ </target>
+ <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72">
+ <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail>
+ <nbprofiledirect>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ </nbprofiledirect>
+ <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true">
+ <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/>
+ <jvmarg value="${profiler.info.jvmargs.agent}"/>
+ <jvmarg line="${profiler.info.jvmargs}"/>
+ <test name="${profile.class}"/>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ </junit>
+ </target>
+ <!--
+ end of pre NB72 profiling section
+ -->
+ <target if="netbeans.home" name="-profile-check">
+ <condition property="profiler.configured">
+ <or>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/>
+ <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/>
+ </or>
+ </condition>
+ </target>
+ <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent">
+ <startprofiler/>
+ <antcall target="run"/>
+ </target>
+ <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcall target="run-single"/>
+ </target>
+ <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/>
+ <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <startprofiler/>
+ <antcall target="test-single"/>
+ </target>
+ <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <startprofiler/>
+ <antcal target="run-test-with-main"/>
+ </target>
+ <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <startprofiler/>
+ <antcall target="run-applet"/>
+ </target>
+ <!--
+ ===============
+ JAVADOC SECTION
+ ===============
+ -->
+ <target depends="init" if="have.sources" name="-javadoc-build">
+ <mkdir dir="${dist.javadoc.dir}"/>
+ <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}">
+ <and>
+ <isset property="endorsed.classpath.cmd.line.arg"/>
+ <not>
+ <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <condition else="" property="bug5101868workaround" value="*.java">
+ <matches pattern="1\.[56](\..*)?" string="${java.version}"/>
+ </condition>
+ <javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+ <classpath>
+ <path path="${javac.classpath}"/>
+ </classpath>
+ <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
+ <filename name="**/*.java"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/*.java"/>
+ <exclude name="*.java"/>
+ </fileset>
+ <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
+ </javadoc>
+ <copy todir="${dist.javadoc.dir}">
+ <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
+ <filename name="**/doc-files/**"/>
+ </fileset>
+ <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
+ <include name="**/doc-files/**"/>
+ </fileset>
+ </copy>
+ </target>
+ <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+ <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+ </target>
+ <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+ <!--
+ =========================
+ TEST COMPILATION SECTION
+ =========================
+ -->
+ <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+ <mkdir dir="${build.test.classes.dir}"/>
+ </target>
+ <target name="-pre-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-test-depend">
+ <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+ <target name="-pre-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+ <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+ <!--
+ =======================
+ TEST EXECUTION SECTION
+ =======================
+ -->
+ <target depends="init" if="have.tests" name="-pre-test-run">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+ <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init" if="have.tests" name="test-report"/>
+ <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+ <target depends="init" if="have.tests" name="-pre-test-run-single">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method">
+ <fail unless="test.class">Must select some files in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method">
+ <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/>
+ <!--
+ =======================
+ TEST DEBUGGING SECTION
+ =======================
+ -->
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <fail unless="test.method">Must select some method in the IDE or set test.method</fail>
+ <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/>
+ </target>
+ <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+ </target>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+ <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/>
+ <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+ <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+ <!--
+ =========================
+ APPLET EXECUTION SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" name="run-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject1:java classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <!--
+ =========================
+ APPLET DEBUGGING SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject3:debug classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+ <!--
+ ===============
+ CLEANUP SECTION
+ ===============
+ -->
+ <target name="-deps-clean-init" unless="built-clean.properties">
+ <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/>
+ <delete file="${built-clean.properties}" quiet="true"/>
+ </target>
+ <target if="already.built.clean.${basedir}" name="-warn-already-built-clean">
+ <echo level="warn" message="Cycle detected: projForTest was already built"/>
+ </target>
+ <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps">
+ <mkdir dir="${build.dir}"/>
+ <touch file="${built-clean.properties}" verbose="false"/>
+ <property file="${built-clean.properties}" prefix="already.built.clean."/>
+ <antcall target="-warn-already-built-clean"/>
+ <propertyfile file="${built-clean.properties}">
+ <entry key="${basedir}" value=""/>
+ </propertyfile>
+ </target>
+ <target depends="init" name="-do-clean">
+ <delete dir="${build.dir}"/>
+ <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
+ </target>
+ <target name="-post-clean">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+ <target name="-check-call-dep">
+ <property file="${call.built.properties}" prefix="already.built."/>
+ <condition property="should.call.dep">
+ <and>
+ <not>
+ <isset property="already.built.${call.subproject}"/>
+ </not>
+ <available file="${call.script}"/>
+ </and>
+ </condition>
+ </target>
+ <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep">
+ <ant antfile="${call.script}" inheritall="false" target="${call.target}">
+ <propertyset>
+ <propertyref prefix="transfer."/>
+ <mapper from="transfer.*" to="*" type="glob"/>
+ </propertyset>
+ </ant>
+ </target>
+</project>
diff --git a/contrib/kotlin/src/test/resources/projForTest/nbproject/genfiles.properties b/contrib/kotlin/src/test/resources/projForTest/nbproject/genfiles.properties
new file mode 100644
index 0000000..5a56d9a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=d1879bfe
+build.xml.script.CRC32=305052e2
+build.xml.stylesheet.CRC32=8064a381@1.79.1.48
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=d1879bfe
+nbproject/build-impl.xml.script.CRC32=f422c90e
+nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48
diff --git a/contrib/kotlin/src/test/resources/projForTest/nbproject/project.properties b/contrib/kotlin/src/test/resources/projForTest/nbproject/project.properties
new file mode 100644
index 0000000..d650ad4
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/nbproject/project.properties
@@ -0,0 +1,78 @@
+annotation.processing.enabled=true
+annotation.processing.enabled.in.editor=false
+annotation.processing.processor.options=
+annotation.processing.processors.list=
+annotation.processing.run.all.processors=true
+annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+build.generated.sources.dir=${build.dir}/generated-sources
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# Files in build.classes.dir which should be excluded from distribution jar
+dist.archive.excludes=
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/projForTest.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+file.reference.kotlin-runtime.jar=C:/Users/Alexander.Baratynski/AppData/Local/Temp/tests-Alexander.Baratynski/j.J/ProjectUnzipper/kotlinc\\lib\\kotlin-runtime.jar
+includes=**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.external.vm=true
+javac.processorpath=\
+ ${javac.classpath}
+javac.source=1.8
+javac.target=1.8
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${kotlinc.classpath}:
+javac.test.processorpath=\
+ ${javac.test.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+kotlinc.classpath=${file.reference.kotlin-runtime.jar}
+main.class=
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+mkdist.disabled=false
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${kotlinc.classpath}:
+# Space-separated list of JVM arguments used when running the project.
+# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
+# To set system properties for unit tests define test-sys-prop.name=value:
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/contrib/kotlin/src/test/resources/projForTest/nbproject/project.xml b/contrib/kotlin/src/test/resources/projForTest/nbproject/project.xml
new file mode 100644
index 0000000..ec962de
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/nbproject/project.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+ <name>projForTest</name>
+ <source-roots>
+ <root id="src.dir"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
+ </test-roots>
+ </data>
+ </configuration>
+</project>
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastAfterIf.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastAfterIf.kt
new file mode 100644
index 0000000..581c589
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastAfterIf.kt
@@ -0,0 +1,9 @@
+package completion
+
+class Num(val value : Int)
+
+fun checkAutoCastAfterIf(obj : Any) {
+ if (obj is Num) {
+ return obj.<caret>
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastAfterIfMethod.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastAfterIfMethod.kt
new file mode 100644
index 0000000..048a1fc
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastAfterIfMethod.kt
@@ -0,0 +1,11 @@
+package completion
+
+class Smth {
+ fun test() {}
+}
+
+fun eval(obj : Any) {
+ if (obj is Smth) {
+ return obj.<caret>()
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastForThis.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastForThis.kt
new file mode 100644
index 0000000..25f3b99
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastForThis.kt
@@ -0,0 +1,17 @@
+package completion
+
+interface Monster {
+
+ public fun test() {
+ if (this is Beholder) {
+ this.<caret>
+ }
+ }
+
+}
+
+class Beholder : Monster {
+
+ fun destroy(){}
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastInWhen.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastInWhen.kt
new file mode 100644
index 0000000..760c856
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkAutoCastInWhen.kt
@@ -0,0 +1,8 @@
+package completion
+
+class Sum(val left : Any, val right : Any)
+
+fun checkAutoCastInWhen(obj : Any) : Any = when (obj) {
+ is Sum -> obj.<caret>
+ else -> 0
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkBasicAny.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkBasicAny.kt
new file mode 100644
index 0000000..884336e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkBasicAny.kt
@@ -0,0 +1,5 @@
+package completion
+
+fun checkBasicAny() {
+ var any : A<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkBasicInt.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkBasicInt.kt
new file mode 100644
index 0000000..16247c8
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkBasicInt.kt
@@ -0,0 +1,5 @@
+package completion
+
+fun checkBasicInt(){
+ var int : In<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkCompanion.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkCompanion.kt
new file mode 100644
index 0000000..afbe4c5
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkCompanion.kt
@@ -0,0 +1,13 @@
+package completion
+
+class ClassWithCompanion {
+ companion object {
+ val companionVal = "companion"
+
+ fun companionFun = companionVal
+ }
+
+ fun checkCompanion() {
+ val check = co<caret>
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkCompletionBeforeDotInCall.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkCompletionBeforeDotInCall.kt
new file mode 100644
index 0000000..6f3ce63
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkCompletionBeforeDotInCall.kt
@@ -0,0 +1,16 @@
+package completion
+
+fun testTop() {
+
+}
+
+class TestSample() {
+ fun main(args : Array<String>) {
+ val testVar = ""
+ test<caret>.testFun()
+ }
+
+ fun testFun() {
+
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkExtendClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkExtendClass.kt
new file mode 100644
index 0000000..07db304
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkExtendClass.kt
@@ -0,0 +1,13 @@
+package completion
+
+open class MySecondClass() {
+}
+
+open class MyFirstClass<T> {
+
+}
+
+class A() : My<caret> {
+ public fun test() {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkImport.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkImport.kt
new file mode 100644
index 0000000..55c08a1
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkImport.kt
@@ -0,0 +1,7 @@
+package completion
+
+import diagnostics.*
+
+fun checkImport() {
+ val obj = Pr<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInCallExpression.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInCallExpression.kt
new file mode 100644
index 0000000..f920789
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInCallExpression.kt
@@ -0,0 +1,9 @@
+package completion
+
+class Temp {
+ fun func(){}
+
+ fun checkInCallExpression(){
+ fu<caret>
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInClassInit.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInClassInit.kt
new file mode 100644
index 0000000..69854c7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInClassInit.kt
@@ -0,0 +1,12 @@
+package completion
+
+val valExternal = "external"
+
+class Some() {
+ private val myVal : Int
+
+ init {
+ val valInternal = 12
+ myVal = va<caret>
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInClassPropertyAccessor.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInClassPropertyAccessor.kt
new file mode 100644
index 0000000..a59c697
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInClassPropertyAccessor.kt
@@ -0,0 +1,8 @@
+package completion
+
+class T(val testParam : Int) {
+ val x : Int get() {
+ val test = 12
+ return te<caret>
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInImport.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInImport.kt
new file mode 100644
index 0000000..b3afe6d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInImport.kt
@@ -0,0 +1,3 @@
+package completion
+
+import diagnostics.<caret>
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInParameterType.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInParameterType.kt
new file mode 100644
index 0000000..4dbb35d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkInParameterType.kt
@@ -0,0 +1,3 @@
+package completion
+
+fun checkInParameterType(a : In<caret>){}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkLocalLambda.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkLocalLambda.kt
new file mode 100644
index 0000000..97ca930
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkLocalLambda.kt
@@ -0,0 +1,10 @@
+package completion
+
+class SomeClass {
+ public fun test() {}
+}
+
+fun checkLocalLambda() {
+ val lambda = { int : Int -> SomeClass() }
+ lambda(0).<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkNonImportedPrivate.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkNonImportedPrivate.kt
new file mode 100644
index 0000000..248e36c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkNonImportedPrivate.kt
@@ -0,0 +1,5 @@
+package completion
+
+fun checkNonImportedPrivate() {
+ priv<caret>
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkStringCompletion.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkStringCompletion.kt
new file mode 100644
index 0000000..33bb4da
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkStringCompletion.kt
@@ -0,0 +1,5 @@
+package completion
+
+fun checkStringCompletion() {
+ "String".tost<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkUnimported.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkUnimported.kt
new file mode 100644
index 0000000..9aeb565
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkUnimported.kt
@@ -0,0 +1,5 @@
+package completion
+
+fun unimportedCompletion() {
+ fu<caret>
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/checkUpperAndLowerCases.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkUpperAndLowerCases.kt
new file mode 100644
index 0000000..d48a737
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/checkUpperAndLowerCases.kt
@@ -0,0 +1,7 @@
+package completion
+
+fun method() {}
+
+fun upper() {
+ MET<caret>
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/completion/pack/functions.kt b/contrib/kotlin/src/test/resources/projForTest/src/completion/pack/functions.kt
new file mode 100644
index 0000000..58447fe
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/completion/pack/functions.kt
@@ -0,0 +1,7 @@
+package completion.pack
+
+fun function1() = 42
+
+fun function2() = 42
+
+private fun privateFunction() = "private"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/SomeClass.java b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/SomeClass.java
new file mode 100644
index 0000000..8a69528
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/SomeClass.java
@@ -0,0 +1,11 @@
+package diagnostics;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class SomeClass {
+ public final Set<JavaClass> roots = new LinkedHashSet<JavaClass>();
+ public SomeClass getSomeClass() { return new SomeClass(); }
+
+ public class JavaClass { public String str = "some string"; }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkCastIsNeverSucceed.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkCastIsNeverSucceed.kt
new file mode 100644
index 0000000..c10bf11
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkCastIsNeverSucceed.kt
@@ -0,0 +1,6 @@
+package diagnostics
+
+fun checkErrors() {
+ val str : String = "smth"
+ val arg : Int = str as Int
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNoTypeMismatch.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNoTypeMismatch.kt
new file mode 100644
index 0000000..21f112c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNoTypeMismatch.kt
@@ -0,0 +1,12 @@
+package diagnostics
+
+interface Base<T> {}
+
+class Proxy<T>(t: T) : Base<T>{
+ val value = t
+}
+
+fun checkNoTypeMismatch() {
+ val base : Base<Int> = Proxy<Int>(5)
+ base.toString()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNoValuePassed.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNoValuePassed.kt
new file mode 100644
index 0000000..8efd9d1
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNoValuePassed.kt
@@ -0,0 +1,7 @@
+package diagnostics
+
+fun str(arg : String) = arg
+
+fun noValuePassed() {
+ str()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNullPointer.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNullPointer.kt
new file mode 100644
index 0000000..d73d99d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkNullPointer.kt
@@ -0,0 +1,5 @@
+package diagnostics
+
+fun returnNull(str : String) = str
+
+fun checkNull() = returnNull(null)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkReassignValue.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkReassignValue.kt
new file mode 100644
index 0000000..a30d779
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkReassignValue.kt
@@ -0,0 +1,6 @@
+package diagnostics
+
+fun changeVal() {
+ val value = 0
+ value += 1
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkTypeMismatch.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkTypeMismatch.kt
new file mode 100644
index 0000000..10284c7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkTypeMismatch.kt
@@ -0,0 +1,12 @@
+package diagnostics
+
+interface Base1<T> {}
+
+class Proxy1<T>(t: T) : Base1<T>{
+ val value = t
+}
+
+fun checkTypeMismatch() {
+ val base : Base1<Int> = Proxy1<String>("str")
+ base.toString()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkTypeParameterOfCollectionDeclaredInJava.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkTypeParameterOfCollectionDeclaredInJava.kt
new file mode 100644
index 0000000..291065d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkTypeParameterOfCollectionDeclaredInJava.kt
@@ -0,0 +1,5 @@
+package diagnostics
+
+fun checkTypeParam() {
+ SomeClass().someClass.roots.map{ it.str }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkWrongImport.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkWrongImport.kt
new file mode 100644
index 0000000..280176c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/checkWrongImport.kt
@@ -0,0 +1,3 @@
+package diagnostics
+
+import smth
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/expectingATopLevelDeclaration.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/expectingATopLevelDeclaration.kt
new file mode 100644
index 0000000..3d2d6ee
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/expectingATopLevelDeclaration.kt
@@ -0,0 +1,6 @@
+package diagnostics
+
+syntax_err
+
+fun func(){
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/parameterIsNeverUsed.kt b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/parameterIsNeverUsed.kt
new file mode 100644
index 0000000..da16aaa
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/diagnostics/parameterIsNeverUsed.kt
@@ -0,0 +1,3 @@
+package diagnostics
+
+fun func(str : String) {}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/folding/class.kt b/contrib/kotlin/src/test/resources/projForTest/src/folding/class.kt
new file mode 100644
index 0000000..622096d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/folding/class.kt
@@ -0,0 +1,26 @@
+package folding
+
+
+// Some class
+class SomeClass {
+
+ init {
+
+ }
+
+ /* comment */
+ fun doNothing() {
+
+ }
+
+ fun someFun() {
+
+ for (i in 0..10) {
+ for (j in 10..20) {
+ doNothing()
+ }
+ }
+
+ }
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/folding/function.kt b/contrib/kotlin/src/test/resources/projForTest/src/folding/function.kt
new file mode 100644
index 0000000..9f11cbe
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/folding/function.kt
@@ -0,0 +1,5 @@
+package folding
+
+fun function(): Int {
+ return 42
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/folding/functionWithBody.kt b/contrib/kotlin/src/test/resources/projForTest/src/folding/functionWithBody.kt
new file mode 100644
index 0000000..b2f7a78
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/folding/functionWithBody.kt
@@ -0,0 +1,9 @@
+package folding
+
+fun functionWithBody() {
+
+ listOf(1,2,3,4,5).forEach {
+ println(it)
+ }
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/folding/licenseHeader.kt b/contrib/kotlin/src/test/resources/projForTest/src/folding/licenseHeader.kt
new file mode 100644
index 0000000..014b334
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/folding/licenseHeader.kt
@@ -0,0 +1,18 @@
+package folding
+
+/*******************************************************************************
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *******************************************************************************/
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/blockCommentBeforeDeclaration.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/blockCommentBeforeDeclaration.after
new file mode 100644
index 0000000..f9f6cf4
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/blockCommentBeforeDeclaration.after
@@ -0,0 +1,16 @@
+package formatting
+
+class Cls {
+ /*
+ */
+ fun test() {
+ }
+
+ /*
+ */
+ val vls = 1
+
+ /*
+ */
+ companion object {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/blockCommentBeforeDeclaration.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/blockCommentBeforeDeclaration.kt
new file mode 100644
index 0000000..5934c62
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/blockCommentBeforeDeclaration.kt
@@ -0,0 +1,15 @@
+package formatting
+
+class Cls{
+/*
+ */
+fun test() {}
+
+/*
+ */
+val vls = 1
+
+/*
+*/
+companion object {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/classesAndPropertiesFormatTest.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/classesAndPropertiesFormatTest.after
new file mode 100644
index 0000000..131714f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/classesAndPropertiesFormatTest.after
@@ -0,0 +1,8 @@
+package formatting
+
+class Foo {
+ fun foo() {
+ }
+
+ val f: String? = null
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/classesAndPropertiesFormatTest.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/classesAndPropertiesFormatTest.kt
new file mode 100644
index 0000000..fd5711d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/classesAndPropertiesFormatTest.kt
@@ -0,0 +1,8 @@
+package formatting
+
+class Foo {
+fun foo() {
+}
+
+val f: String? = null
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/commentOnTheLastLineOfLambda.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/commentOnTheLastLineOfLambda.after
new file mode 100644
index 0000000..0b2523e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/commentOnTheLastLineOfLambda.after
@@ -0,0 +1,8 @@
+package formatting
+
+fun main(args: Array<String>) {
+ listOf("A").map {
+ null
+// Can't add newlines in 'map' lambda if this is the last/only line in the lambda
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/commentOnTheLastLineOfLambda.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/commentOnTheLastLineOfLambda.kt
new file mode 100644
index 0000000..1d3d7d1
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/commentOnTheLastLineOfLambda.kt
@@ -0,0 +1,8 @@
+package formatting
+
+fun main(args: Array<String>) {
+listOf("A").map {
+null
+// Can't add newlines in 'map' lambda if this is the last/only line in the lambda
+}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInDoWhile.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInDoWhile.after
new file mode 100644
index 0000000..be7e21e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInDoWhile.after
@@ -0,0 +1,7 @@
+package formatting
+
+fun aa() {
+ do {
+ println("some")
+ } while (true)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInDoWhile.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInDoWhile.kt
new file mode 100644
index 0000000..db14229
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInDoWhile.kt
@@ -0,0 +1,7 @@
+package formatting
+
+fun aa() {
+ do {
+ println("some")
+ } while (true)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInIfExpressionBlock.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInIfExpressionBlock.after
new file mode 100644
index 0000000..1286559
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInIfExpressionBlock.after
@@ -0,0 +1,9 @@
+package formatting
+
+fun sm() {
+ val aa = if (true) {
+ 1
+ } else {
+ 2
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInIfExpressionBlock.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInIfExpressionBlock.kt
new file mode 100644
index 0000000..3b8ebf7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInIfExpressionBlock.kt
@@ -0,0 +1,9 @@
+package formatting
+
+fun sm() {
+ val aa = if (true) {
+ 1
+ } else {
+2
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInPropertyAccessor.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInPropertyAccessor.after
new file mode 100644
index 0000000..2bbd18b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInPropertyAccessor.after
@@ -0,0 +1,9 @@
+package formatting
+
+class C {
+ var someProp: Int
+ get() = throw UnsupportedOperationException()
+ set(value) {
+ println("10")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInPropertyAccessor.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInPropertyAccessor.kt
new file mode 100644
index 0000000..60b76f7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInPropertyAccessor.kt
@@ -0,0 +1,9 @@
+package formatting
+
+class C {
+ var someProp: Int
+ get() = throw UnsupportedOperationException()
+ set(value) {
+ println("10")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInWhenEntry.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInWhenEntry.after
new file mode 100644
index 0000000..08291d8
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInWhenEntry.after
@@ -0,0 +1,9 @@
+package formatting
+
+fun a() {
+ when (1) {
+ is Int {
+ println()
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInWhenEntry.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInWhenEntry.kt
new file mode 100644
index 0000000..96bcf53
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/indentInWhenEntry.kt
@@ -0,0 +1,9 @@
+package formatting
+
+fun a() {
+ when (1) {
+ is Int {
+ println()
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/initIndent.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/initIndent.after
new file mode 100644
index 0000000..9a4d7d0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/initIndent.after
@@ -0,0 +1,7 @@
+package formatting
+
+class Test {
+ init {
+ val a = 1
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/initIndent.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/initIndent.kt
new file mode 100644
index 0000000..c1cba83
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/initIndent.kt
@@ -0,0 +1,7 @@
+package formatting
+
+class Test {
+init {
+ val a = 1
+}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/lambdaInBlock.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/lambdaInBlock.after
new file mode 100644
index 0000000..76da355
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/lambdaInBlock.after
@@ -0,0 +1,7 @@
+package formatting
+
+fun test() {
+ listOf(1, 2).forEach { number ->
+ println(number)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/lambdaInBlock.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/lambdaInBlock.kt
new file mode 100644
index 0000000..76da355
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/lambdaInBlock.kt
@@ -0,0 +1,7 @@
+package formatting
+
+fun test() {
+ listOf(1, 2).forEach { number ->
+ println(number)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/newLineAfterImportsAndPackage.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/newLineAfterImportsAndPackage.after
new file mode 100644
index 0000000..58e90ed
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/newLineAfterImportsAndPackage.after
@@ -0,0 +1,6 @@
+package formatting
+
+import completion
+import diagnostics
+
+fun func() {}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/newLineAfterImportsAndPackage.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/newLineAfterImportsAndPackage.kt
new file mode 100644
index 0000000..acf7c62
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/newLineAfterImportsAndPackage.kt
@@ -0,0 +1,4 @@
+package formatting
+import completion
+import diagnostics
+fun func() {}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/objectsAndLocalFunctionsFormatTest.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/objectsAndLocalFunctionsFormatTest.after
new file mode 100644
index 0000000..48fb448
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/objectsAndLocalFunctionsFormatTest.after
@@ -0,0 +1,8 @@
+package formatting
+
+object Fooo {
+ fun foo() {
+ fun localFoo() {
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/objectsAndLocalFunctionsFormatTest.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/objectsAndLocalFunctionsFormatTest.kt
new file mode 100644
index 0000000..e8eca52
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/objectsAndLocalFunctionsFormatTest.kt
@@ -0,0 +1,8 @@
+package formatting
+
+object Fooo {
+ fun foo() {
+fun localFoo() {
+ }
+}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/packageFunctionsFormatTest.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/packageFunctionsFormatTest.after
new file mode 100644
index 0000000..3b31310
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/packageFunctionsFormatTest.after
@@ -0,0 +1,5 @@
+package formatting
+
+fun foo() {
+ val s = ""
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/packageFunctionsFormatTest.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/packageFunctionsFormatTest.kt
new file mode 100644
index 0000000..a9b7016
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/packageFunctionsFormatTest.kt
@@ -0,0 +1,5 @@
+package formatting
+
+fun foo() {
+val s = ""
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withBlockComments.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withBlockComments.after
new file mode 100644
index 0000000..e280179
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withBlockComments.after
@@ -0,0 +1,12 @@
+package formatting
+
+class Hello {
+ /*
+ class classInComment {
+ fun someFun {
+ }
+ }
+ */
+ fun someFun() {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withBlockComments.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withBlockComments.kt
new file mode 100644
index 0000000..e280179
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withBlockComments.kt
@@ -0,0 +1,12 @@
+package formatting
+
+class Hello {
+ /*
+ class classInComment {
+ fun someFun {
+ }
+ }
+ */
+ fun someFun() {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withJavaDoc.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withJavaDoc.after
new file mode 100644
index 0000000..feda9e8
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withJavaDoc.after
@@ -0,0 +1,14 @@
+package formatting
+
+/**
+ *
+ *
+ */
+class SomeTest {
+ /**
+ *
+ * @param x
+ */
+ fun someFun(x: Int) {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withJavaDoc.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withJavaDoc.kt
new file mode 100644
index 0000000..957fde6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withJavaDoc.kt
@@ -0,0 +1,14 @@
+package formatting
+
+/**
+*
+*
+*/
+class SomeTest {
+ /**
+ *
+ * @param x
+ */
+fun someFun(x: Int) {
+}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withLineComments.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withLineComments.after
new file mode 100644
index 0000000..41ea012
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withLineComments.after
@@ -0,0 +1,11 @@
+package formatting
+
+// Hello
+// Some
+class SomeCls {
+ // Test
+// Test1
+// Test2
+ fun function() {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withLineComments.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withLineComments.kt
new file mode 100644
index 0000000..9a4c5ae
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withLineComments.kt
@@ -0,0 +1,11 @@
+package formatting
+
+// Hello
+// Some
+class SomeCls {
+// Test
+// Test1
+// Test2
+ fun function() {
+}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withMutableVariable.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withMutableVariable.after
new file mode 100644
index 0000000..3137b67
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withMutableVariable.after
@@ -0,0 +1,8 @@
+package formatting
+
+class Cl {
+ var someProp: Int
+ get() = throw UnsupportedOperationException()
+ set(value) {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withMutableVariable.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withMutableVariable.kt
new file mode 100644
index 0000000..6610c83
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withMutableVariable.kt
@@ -0,0 +1,8 @@
+package formatting
+
+class Cl {
+ var someProp: Int
+ get() = throw UnsupportedOperationException()
+ set(value) {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withWhitespaceBeforeBrace.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withWhitespaceBeforeBrace.after
new file mode 100644
index 0000000..d880c1c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withWhitespaceBeforeBrace.after
@@ -0,0 +1,19 @@
+package formatting
+
+class Some {
+
+ init {
+
+ }
+
+ fun some() {
+
+ }
+
+ fun some2() {
+ if (true) {
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withWhitespaceBeforeBrace.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withWhitespaceBeforeBrace.kt
new file mode 100644
index 0000000..9874bba
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withWhitespaceBeforeBrace.kt
@@ -0,0 +1,19 @@
+package formatting
+
+class Some{
+
+ init{
+
+ }
+
+ fun some(){
+
+ }
+
+ fun some2() {
+ if (true){
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withoutComments.after b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withoutComments.after
new file mode 100644
index 0000000..2293b83
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withoutComments.after
@@ -0,0 +1,8 @@
+package formatting
+
+class SimpleTest
+
+fun topLevelFun() {
+ fun localFun() {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/formatting/withoutComments.kt b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withoutComments.kt
new file mode 100644
index 0000000..c6d0f4b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/formatting/withoutComments.kt
@@ -0,0 +1,8 @@
+package formatting
+
+class SimpleTest
+
+fun topLevelFun() {
+ fun localFun() {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/blockComment.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/blockComment.kt
new file mode 100644
index 0000000..9b371e5
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/blockComment.kt
@@ -0,0 +1,3 @@
+/* test
+test
+*/
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/companionObject.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/companionObject.kt
new file mode 100644
index 0000000..e275175
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/companionObject.kt
@@ -0,0 +1,4 @@
+class C {
+ companion object {
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/forKeyword.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/forKeyword.kt
new file mode 100644
index 0000000..98756a9
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/forKeyword.kt
@@ -0,0 +1 @@
+for
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/function.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/function.kt
new file mode 100644
index 0000000..4a86b52
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/function.kt
@@ -0,0 +1,3 @@
+fun foo(){
+ fun innerFun(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/getterSetter.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/getterSetter.kt
new file mode 100644
index 0000000..17e520d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/getterSetter.kt
@@ -0,0 +1,5 @@
+class Cl {
+ var x: Int = 1
+ set() = 2
+ get()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/importKeyword.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/importKeyword.kt
new file mode 100644
index 0000000..780b92e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/importKeyword.kt
@@ -0,0 +1 @@
+import smth
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/inKeyword.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/inKeyword.kt
new file mode 100644
index 0000000..f087d89
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/inKeyword.kt
@@ -0,0 +1 @@
+in
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/interfaceKeyword.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/interfaceKeyword.kt
new file mode 100644
index 0000000..bdca5fd
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/interfaceKeyword.kt
@@ -0,0 +1,2 @@
+interface Interf {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/keywordWithText.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/keywordWithText.kt
new file mode 100644
index 0000000..a88abd8
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/keywordWithText.kt
@@ -0,0 +1 @@
+in some
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/openKeyword.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/openKeyword.kt
new file mode 100644
index 0000000..33d4878
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/openKeyword.kt
@@ -0,0 +1 @@
+open class MyClass
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/singleLineComment.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/singleLineComment.kt
new file mode 100644
index 0000000..d2934b1
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/singleLineComment.kt
@@ -0,0 +1 @@
+//single line comment
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/softImportKeyword.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/softImportKeyword.kt
new file mode 100644
index 0000000..e8ef37a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/softImportKeyword.kt
@@ -0,0 +1,3 @@
+class some {
+ import
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/softKeywords.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/softKeywords.kt
new file mode 100644
index 0000000..306c26c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/softKeywords.kt
@@ -0,0 +1,5 @@
+import some
+
+open abstract class Cls {
+ import
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/stringInterpolation.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/stringInterpolation.kt
new file mode 100644
index 0000000..99a97b6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/stringInterpolation.kt
@@ -0,0 +1,2 @@
+val xyz = 10
+"test: $xyz"
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/stringToken.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/stringToken.kt
new file mode 100644
index 0000000..c4a7336
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/stringToken.kt
@@ -0,0 +1 @@
+"something"
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/highlighting/textWithTokenInside.kt b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/textWithTokenInside.kt
new file mode 100644
index 0000000..c163a96
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/highlighting/textWithTokenInside.kt
@@ -0,0 +1 @@
+kotlin
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterEquals.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterEquals.after
new file mode 100644
index 0000000..58d33aa
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterEquals.after
@@ -0,0 +1,4 @@
+package indentation
+
+fun contains(p: Point): Boolean =
+ <caret>
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterEquals.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterEquals.kt
new file mode 100644
index 0000000..2f8249a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterEquals.kt
@@ -0,0 +1,3 @@
+package indentation
+
+fun contains(p: Point): Boolean = <caret>
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOneOpenBrace.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOneOpenBrace.after
new file mode 100644
index 0000000..6fab6c2
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOneOpenBrace.after
@@ -0,0 +1,4 @@
+package indentation
+
+fun tt(){
+ <caret>
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOneOpenBrace.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOneOpenBrace.kt
new file mode 100644
index 0000000..91c9614
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOneOpenBrace.kt
@@ -0,0 +1,3 @@
+package indentation
+
+fun tt(){<caret>
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOpenBraceWithShift.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOpenBraceWithShift.after
new file mode 100644
index 0000000..a6b2fed
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOpenBraceWithShift.after
@@ -0,0 +1,6 @@
+package indentation
+
+data class User(
+ val name: String) {
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOpenBraceWithShift.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOpenBraceWithShift.kt
new file mode 100644
index 0000000..e388978
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOpenBraceWithShift.kt
@@ -0,0 +1,4 @@
+package indentation
+
+data class User(
+ val name: String) {<caret>}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorIfWithoutBraces.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorIfWithoutBraces.after
new file mode 100644
index 0000000..13ba509
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorIfWithoutBraces.after
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+ if (true)
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorIfWithoutBraces.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorIfWithoutBraces.kt
new file mode 100644
index 0000000..b7b6a27
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorIfWithoutBraces.kt
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+ if (true)<caret>
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorWhileWithoutBraces.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorWhileWithoutBraces.after
new file mode 100644
index 0000000..784714c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorWhileWithoutBraces.after
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+ while (true)
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorWhileWithoutBraces.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorWhileWithoutBraces.kt
new file mode 100644
index 0000000..f83ccf3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/afterOperatorWhileWithoutBraces.kt
@@ -0,0 +1,5 @@
+package indentation
+
+fun tt() {
+ while (true)<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeCloseBrace.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeCloseBrace.after
new file mode 100644
index 0000000..d09d6b0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeCloseBrace.after
@@ -0,0 +1,5 @@
+package indentation
+
+{
+
+<caret>}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeCloseBrace.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeCloseBrace.kt
new file mode 100644
index 0000000..2e5b03e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeCloseBrace.kt
@@ -0,0 +1,4 @@
+package indentation
+
+{
+<caret>}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeFunctionStart.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeFunctionStart.after
new file mode 100644
index 0000000..19b5bcb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeFunctionStart.after
@@ -0,0 +1,5 @@
+package indentation
+
+
+<caret>fun tt() {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeFunctionStart.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeFunctionStart.kt
new file mode 100644
index 0000000..ebfb1df
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeFunctionStart.kt
@@ -0,0 +1,4 @@
+package indentation
+
+<caret>fun tt() {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeNestedCloseBrace.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeNestedCloseBrace.after
new file mode 100644
index 0000000..bb23aaa
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeNestedCloseBrace.after
@@ -0,0 +1,8 @@
+package indentation
+
+fun someFunc() {
+ if (10 > 9) {
+
+
+ <caret>}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeNestedCloseBrace.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeNestedCloseBrace.kt
new file mode 100644
index 0000000..d856b58
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeNestedCloseBrace.kt
@@ -0,0 +1,7 @@
+package indentation
+
+fun someFunc() {
+ if (10 > 9) {
+
+ <caret>}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeTwiceNestedCloseBrace.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeTwiceNestedCloseBrace.after
new file mode 100644
index 0000000..f229f18
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeTwiceNestedCloseBrace.after
@@ -0,0 +1,10 @@
+package indentation
+
+fun newFunc() {
+ if (5 == 5) {
+ if (10 < 15) {
+
+
+ <caret>}
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeTwiceNestedCloseBrace.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeTwiceNestedCloseBrace.kt
new file mode 100644
index 0000000..440080b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/beforeTwiceNestedCloseBrace.kt
@@ -0,0 +1,9 @@
+package indentation
+
+fun newFunc() {
+ if (5 == 5) {
+ if (10 < 15) {
+
+ <caret>}
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnDifferentLine.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnDifferentLine.after
new file mode 100644
index 0000000..5802433
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnDifferentLine.after
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+ <caret>
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnDifferentLine.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnDifferentLine.kt
new file mode 100644
index 0000000..bc1abdd
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnDifferentLine.kt
@@ -0,0 +1,5 @@
+package indentation
+
+fun tt() {<caret>
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine.after
new file mode 100644
index 0000000..972bd48
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine.after
@@ -0,0 +1,5 @@
+package indentation
+
+{
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine.kt
new file mode 100644
index 0000000..4482941
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine.kt
@@ -0,0 +1,3 @@
+package indentation
+
+{<caret>}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine2.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine2.after
new file mode 100644
index 0000000..cf678b6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine2.after
@@ -0,0 +1,5 @@
+package indentation
+
+fun indTest() {
+ <caret>>
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine2.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine2.kt
new file mode 100644
index 0000000..db9326f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/betweenBracesOnOneLine2.kt
@@ -0,0 +1,3 @@
+package indentation
+
+fun indTest() { <caret> }
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/breakLineAfterIfWithoutBraces.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/breakLineAfterIfWithoutBraces.after
new file mode 100644
index 0000000..9086c5d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/breakLineAfterIfWithoutBraces.after
@@ -0,0 +1,7 @@
+package indentation
+
+fun tt() {
+ if (true)
+ true
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/breakLineAfterIfWithoutBraces.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/breakLineAfterIfWithoutBraces.kt
new file mode 100644
index 0000000..b713715
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/breakLineAfterIfWithoutBraces.kt
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+ if (true)
+ true<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationAfterDotCall.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationAfterDotCall.after
new file mode 100644
index 0000000..448b212
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationAfterDotCall.after
@@ -0,0 +1,6 @@
+package indentation
+
+fun some() {
+ listOf(1, 2).
+ <caret>map { it >= 2 }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationAfterDotCall.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationAfterDotCall.kt
new file mode 100644
index 0000000..b9ff3df
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationAfterDotCall.kt
@@ -0,0 +1,5 @@
+package indentation
+
+fun some() {
+ listOf(1, 2).<caret>map { it >= 2 }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationBeforeFunName.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationBeforeFunName.after
new file mode 100644
index 0000000..fa70714
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationBeforeFunName.after
@@ -0,0 +1,4 @@
+package indentation
+
+fun
+ <caret>test() {}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationBeforeFunName.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationBeforeFunName.kt
new file mode 100644
index 0000000..cb2fab3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationBeforeFunName.kt
@@ -0,0 +1,3 @@
+package indentation
+
+fun <caret>test() {}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationInMultiLineExpression.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationInMultiLineExpression.after
new file mode 100644
index 0000000..b527499
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationInMultiLineExpression.after
@@ -0,0 +1,7 @@
+package indentation
+
+fun foo() {
+ "longstring".substring(
+ 1,
+ <caret>)
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationInMultiLineExpression.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationInMultiLineExpression.kt
new file mode 100644
index 0000000..a5a4f3a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/continuationInMultiLineExpression.kt
@@ -0,0 +1,6 @@
+package indentation
+
+fun foo() {
+ "longstring".substring(
+ 1,<caret>)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/indentBeforeWhile.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/indentBeforeWhile.after
new file mode 100644
index 0000000..aaa8471
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/indentBeforeWhile.after
@@ -0,0 +1,7 @@
+package indentation
+
+fun test() {
+ val some = 1
+
+ <caret>while (true) {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/indentBeforeWhile.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/indentBeforeWhile.kt
new file mode 100644
index 0000000..d107104
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/indentBeforeWhile.kt
@@ -0,0 +1,6 @@
+package indentation
+
+fun test() {
+ val some = 1
+ <caret>while (true) {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/lineBreakSaveIndent.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/lineBreakSaveIndent.after
new file mode 100644
index 0000000..f080d89
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/lineBreakSaveIndent.after
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/lineBreakSaveIndent.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/lineBreakSaveIndent.kt
new file mode 100644
index 0000000..7094f62
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/lineBreakSaveIndent.kt
@@ -0,0 +1,5 @@
+package indentation
+
+fun tt() {
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithBraces.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithBraces.after
new file mode 100644
index 0000000..2bcaa5a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithBraces.after
@@ -0,0 +1,9 @@
+package indentation
+
+fun tt() {
+ if (true) {
+ if (true) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithBraces.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithBraces.kt
new file mode 100644
index 0000000..5ab2ea3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithBraces.kt
@@ -0,0 +1,8 @@
+package indentation
+
+fun tt() {
+ if (true) {
+ if (true) {<caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithoutBraces.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithoutBraces.after
new file mode 100644
index 0000000..e8ad6ac
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithoutBraces.after
@@ -0,0 +1,7 @@
+package indentation
+
+fun tt() {
+ if (true)
+ if (true)
+ <caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithoutBraces.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithoutBraces.kt
new file mode 100644
index 0000000..0b56965
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/nestedOperatorsWithoutBraces.kt
@@ -0,0 +1,6 @@
+package indentation
+
+fun tt() {
+ if (true)
+ if (true)<caret>
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineInParameters.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineInParameters.after
new file mode 100644
index 0000000..89e0099
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineInParameters.after
@@ -0,0 +1,7 @@
+package indentation
+
+fun test() {
+ fun some(a: Int, b: Int) {}
+ some(
+ <caret>12, 3)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineInParameters.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineInParameters.kt
new file mode 100644
index 0000000..ea88541
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineInParameters.kt
@@ -0,0 +1,6 @@
+package indentation
+
+fun test() {
+ fun some(a: Int, b: Int) {}
+ some(<caret>12, 3)
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineWhenCaretAtPosition0.after b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineWhenCaretAtPosition0.after
new file mode 100644
index 0000000..9098e65
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineWhenCaretAtPosition0.after
@@ -0,0 +1,2 @@
+
+<caret>package indentation
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineWhenCaretAtPosition0.kt b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineWhenCaretAtPosition0.kt
new file mode 100644
index 0000000..276155f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/indentation/newLineWhenCaretAtPosition0.kt
@@ -0,0 +1 @@
+<caret>package indentation
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.after
new file mode 100644
index 0000000..9848363
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.after
@@ -0,0 +1,3 @@
+package intentions
+
+class AddValToParameter(val par: String)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.caret
new file mode 100644
index 0000000..90ff353
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.caret
@@ -0,0 +1,3 @@
+package intentions
+
+class AddValToParameter(p<caret>ar: String)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.kt
new file mode 100644
index 0000000..5b22c8b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/addValToConstructorParameter.kt
@@ -0,0 +1,3 @@
+package intentions
+
+class AddValToParameter(par: String)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.after
new file mode 100644
index 0000000..c88a1b3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.after
@@ -0,0 +1,3 @@
+package intentions
+
+fun changeReturnType(): Int = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.caret
new file mode 100644
index 0000000..37e7160
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.caret
@@ -0,0 +1,3 @@
+package intentions
+
+fun changeReturnType(): String = 42<caret>
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.kt
new file mode 100644
index 0000000..3c6b4bb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/changeReturnType.kt
@@ -0,0 +1,3 @@
+package intentions
+
+fun changeReturnType(): String = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.after
new file mode 100644
index 0000000..be6f2a3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.after
@@ -0,0 +1,8 @@
+package intentions
+
+class ConvertPropertyInitToGetter {
+
+ val property: Int
+ get() = 42
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.caret
new file mode 100644
index 0000000..2b413e0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.caret
@@ -0,0 +1,7 @@
+package intentions
+
+class ConvertPropertyInitToGetter {
+
+ val property = <caret>42
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.kt
new file mode 100644
index 0000000..b5fae80
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertPropertyInitializerToGetter.kt
@@ -0,0 +1,7 @@
+package intentions
+
+class ConvertPropertyInitToGetter {
+
+ val property = 42
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.after
new file mode 100644
index 0000000..cd5c742
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.after
@@ -0,0 +1,5 @@
+package intentions
+
+fun convertToBlockBodyTest(): Int {
+ return 42
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.caret
new file mode 100644
index 0000000..47b078c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.caret
@@ -0,0 +1,3 @@
+package intentions
+
+fun convertToBlockBodyTest() = <caret>42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.kt
new file mode 100644
index 0000000..1f892ba
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToBlockBody.kt
@@ -0,0 +1,3 @@
+package intentions
+
+fun convertToBlockBodyTest() = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.after
new file mode 100644
index 0000000..873c568
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.after
@@ -0,0 +1,5 @@
+package intentions
+
+fun convertToConcatenatedString(s: String) {
+ val str = "Hello, " + s
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.caret
new file mode 100644
index 0000000..7fca3de
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.caret
@@ -0,0 +1,5 @@
+package intentions
+
+fun convertToConcatenatedString(s: String) {
+ val str = "Hello, $s<caret>"
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.kt
new file mode 100644
index 0000000..ad50379
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToConcatenatedString.kt
@@ -0,0 +1,5 @@
+package intentions
+
+fun convertToConcatenatedString(s: String) {
+ val str = "Hello, $s"
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.after
new file mode 100644
index 0000000..aed610f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.after
@@ -0,0 +1,3 @@
+package intentions
+
+fun convertToExpressionBody(): Int = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.caret
new file mode 100644
index 0000000..a90a44c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.caret
@@ -0,0 +1,5 @@
+package intentions
+
+fun convertToExpressionBody(): Int {
+ return<caret> 42
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.kt
new file mode 100644
index 0000000..73edc44
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToExpressionBody.kt
@@ -0,0 +1,5 @@
+package intentions
+
+fun convertToExpressionBody(): Int {
+ return 42
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.after
new file mode 100644
index 0000000..d957935
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.after
@@ -0,0 +1,13 @@
+package intentions
+
+sealed class ProtocolState {
+ object WAITING : ProtocolState() {
+ override fun signal() = TALKING
+ }
+
+ object TALKING : ProtocolState() {
+ override fun signal() = WAITING
+ }
+
+ abstract fun signal(): ProtocolState
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.caret
new file mode 100644
index 0000000..a22e6d2
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.caret
@@ -0,0 +1,13 @@
+package intentions
+
+enum class Protoco<caret>lState {
+ WAITING {
+ override fun signal() = TALKING
+ },
+
+ TALKING {
+ override fun signal() = WAITING
+ };
+
+ abstract fun signal(): ProtocolState
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.kt
new file mode 100644
index 0000000..6cbd33c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToSealedClass.kt
@@ -0,0 +1,13 @@
+package intentions
+
+enum class ProtocolState {
+ WAITING {
+ override fun signal() = TALKING
+ },
+
+ TALKING {
+ override fun signal() = WAITING
+ };
+
+ abstract fun signal(): ProtocolState
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.after
new file mode 100644
index 0000000..82bcbbb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.after
@@ -0,0 +1,3 @@
+package intentions
+
+fun convertTotringTemplate() = "1214"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.caret
new file mode 100644
index 0000000..5f7e193
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.caret
@@ -0,0 +1,3 @@
+package intentions
+
+fun convertTotringTemplate() = "12" + "<caret>14"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.kt
new file mode 100644
index 0000000..e4e214e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertToStringTemplate.kt
@@ -0,0 +1,3 @@
+package intentions
+
+fun convertTotringTemplate() = "12" + "14"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.after
new file mode 100644
index 0000000..cc451e4
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.after
@@ -0,0 +1,7 @@
+package intentions
+
+fun convertTwoComparisons() {
+ val integer = 5
+ if (integer in 4..6) {
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.caret
new file mode 100644
index 0000000..a7e9e68
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.caret
@@ -0,0 +1,7 @@
+package intentions
+
+fun convertTwoComparisons() {
+ val integer = 5
+ if (integer > 3 &<caret>& integer < 7) {
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.kt
new file mode 100644
index 0000000..6a56381
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/convertTwoComparisons.kt
@@ -0,0 +1,7 @@
+package intentions
+
+fun convertTwoComparisons() {
+ val integer = 5
+ if (integer > 3 && integer < 7) {
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.after
new file mode 100644
index 0000000..50701a9
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.after
@@ -0,0 +1,8 @@
+package intentions
+
+fun mergeIfs() {
+ val integer = 5
+ if (integer > 3 && integer < 7) {
+
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.caret
new file mode 100644
index 0000000..639884f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.caret
@@ -0,0 +1,9 @@
+package intentions
+
+fun mergeIfs() {
+ val integer = 5
+ if (<caret>integer > 3) {
+ if (integer < 7) {
+ }
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.kt
new file mode 100644
index 0000000..355183f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/mergeIfs.kt
@@ -0,0 +1,9 @@
+package intentions
+
+fun mergeIfs() {
+ val integer = 5
+ if (integer > 3) {
+ if (integer < 7) {
+ }
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.after
new file mode 100644
index 0000000..a70ca1a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.after
@@ -0,0 +1,5 @@
+package intentions
+
+fun removeBraces() {
+ if (42 > 3) return
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.caret
new file mode 100644
index 0000000..d9346e5
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.caret
@@ -0,0 +1,7 @@
+package intentions
+
+fun removeBraces() {
+ if (42 > 3) {<caret>
+ return
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.kt
new file mode 100644
index 0000000..4b264d3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeBraces.kt
@@ -0,0 +1,7 @@
+package intentions
+
+fun removeBraces() {
+ if (42 > 3) {
+ return
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.after
new file mode 100644
index 0000000..3740068
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.after
@@ -0,0 +1,3 @@
+package intentions
+
+class RemoveBraces
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.caret
new file mode 100644
index 0000000..269ef6f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.caret
@@ -0,0 +1,5 @@
+package intentions
+
+class RemoveBraces {
+<caret>
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.kt
new file mode 100644
index 0000000..3aca8b2
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyClassBody.kt
@@ -0,0 +1,5 @@
+package intentions
+
+class RemoveBraces {
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.after
new file mode 100644
index 0000000..0585d97
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.after
@@ -0,0 +1,3 @@
+package intentions
+
+class EmptyPrimary
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.caret
new file mode 100644
index 0000000..8f1bc7d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.caret
@@ -0,0 +1,3 @@
+package intentions
+
+class EmptyPrimary(<caret>)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.kt
new file mode 100644
index 0000000..c196849
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptyPrimaryConstructor.kt
@@ -0,0 +1,3 @@
+package intentions
+
+class EmptyPrimary()
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.after
new file mode 100644
index 0000000..5f71cdb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.after
@@ -0,0 +1,5 @@
+package intentions
+
+class SecondaryConstructor {
+ constructor()
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.caret
new file mode 100644
index 0000000..2a73634
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.caret
@@ -0,0 +1,5 @@
+package intentions
+
+class SecondaryConstructor {
+ constructor() {<caret>}
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.kt
new file mode 100644
index 0000000..695911f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeEmptySecondaryConstructor.kt
@@ -0,0 +1,5 @@
+package intentions
+
+class SecondaryConstructor {
+ constructor() {}
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.after
new file mode 100644
index 0000000..832da65
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.after
@@ -0,0 +1,3 @@
+package intentions
+
+fun explicit() = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.caret
new file mode 100644
index 0000000..259fe0f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.caret
@@ -0,0 +1,4 @@
+package intentions
+
+fun explicit(): <caret>Int = 42
+
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.kt
new file mode 100644
index 0000000..ff76385
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeExplicitType.kt
@@ -0,0 +1,3 @@
+package intentions
+
+fun explicit(): Int = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.after
new file mode 100644
index 0000000..3f7e9bd
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.after
@@ -0,0 +1,4 @@
+package intentions
+
+fun removeEmptyParenthesesFromLambdaCall(strs: Array<String>) = strs.map {}
+
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.caret
new file mode 100644
index 0000000..26c907b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.caret
@@ -0,0 +1,3 @@
+package intentions
+
+fun removeEmptyParenthesesFromLambdaCall(strs: Array<String>) = strs.map<caret>() {}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.kt
new file mode 100644
index 0000000..a4d2844
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/removeParenthesesFromLambdaCall.kt
@@ -0,0 +1,3 @@
+package intentions
+
+fun removeEmptyParenthesesFromLambdaCall(strs: Array<String>) = strs.map() {}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.after
new file mode 100644
index 0000000..9993ec9
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.after
@@ -0,0 +1,7 @@
+package intentions
+
+fun replaceSizeCheckWithIsNotEmpty(strs: Array<String>) {
+ if (strs.isNotEmpty()) {
+
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.caret
new file mode 100644
index 0000000..f2a7302
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.caret
@@ -0,0 +1,7 @@
+package intentions
+
+fun replaceSizeCheckWithIsNotEmpty(strs: Array<String>) {
+ if (<caret>strs.size > 0) {
+
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.kt
new file mode 100644
index 0000000..1db78e1
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/replaceSizeCheckWithIsNotEmpty.kt
@@ -0,0 +1,7 @@
+package intentions
+
+fun replaceSizeCheckWithIsNotEmpty(strs: Array<String>) {
+ if (strs.size > 0) {
+
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.after
new file mode 100644
index 0000000..7162daf
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.after
@@ -0,0 +1,3 @@
+package intentions
+
+fun specifyType(): String = "str"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.caret
new file mode 100644
index 0000000..bfac830
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.caret
@@ -0,0 +1,3 @@
+package intentions
+
+fun specifyType()<caret> = "str"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.kt
new file mode 100644
index 0000000..84031ac
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/specifyType.kt
@@ -0,0 +1,3 @@
+package intentions
+
+fun specifyType() = "str"
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.after
new file mode 100644
index 0000000..09fa40e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.after
@@ -0,0 +1,8 @@
+package intentions
+
+fun splitIf() {
+ val integer = 5
+ if (integer > 3) {
+ if (integer != 5) {}
+ }
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.caret
new file mode 100644
index 0000000..e5ed842
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.caret
@@ -0,0 +1,6 @@
+package intentions
+
+fun splitIf() {
+ val integer = 5
+ <caret>if (integer > 3 && integer != 5) {}
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.kt
new file mode 100644
index 0000000..bf837fe
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/splitIf.kt
@@ -0,0 +1,6 @@
+package intentions
+
+fun splitIf() {
+ val integer = 5
+ if (integer > 3 && integer != 5) {}
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.after b/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.after
new file mode 100644
index 0000000..cad1f10
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.after
@@ -0,0 +1,7 @@
+package intentions
+
+infix fun Int.inf(p: Int) = this + p
+
+fun toInfix() {
+ val res = 42 inf 42
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.caret b/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.caret
new file mode 100644
index 0000000..5675a50
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.caret
@@ -0,0 +1,7 @@
+package intentions
+
+infix fun Int.inf(p: Int) = this + p
+
+fun toInfix() {
+ val res = 42.in<caret>f(42)
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.kt b/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.kt
new file mode 100644
index 0000000..0221342
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/intentions/toInfix.kt
@@ -0,0 +1,7 @@
+package intentions
+
+infix fun Int.inf(p: Int) = this + p
+
+fun toInfix() {
+ val res = 42.inf(42)
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/interface.after b/contrib/kotlin/src/test/resources/projForTest/src/j2k/interface.after
new file mode 100644
index 0000000..6481df1
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/interface.after
@@ -0,0 +1,5 @@
+package j2k
+
+interface SomeInterface {
+ fun hello()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/interface.java b/contrib/kotlin/src/test/resources/projForTest/src/j2k/interface.java
new file mode 100644
index 0000000..ccd043f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/interface.java
@@ -0,0 +1,5 @@
+package j2k;
+
+public interface SomeInterface {
+ public void hello();
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/mixed.after b/contrib/kotlin/src/test/resources/projForTest/src/j2k/mixed.after
new file mode 100644
index 0000000..0324ed0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/mixed.after
@@ -0,0 +1,11 @@
+package j2k
+
+class MixedClass {
+ fun hello() {
+ System.out.println("hello")
+ }
+
+ companion object {
+ fun staticMethod() {}
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/mixed.java b/contrib/kotlin/src/test/resources/projForTest/src/j2k/mixed.java
new file mode 100644
index 0000000..41769d7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/mixed.java
@@ -0,0 +1,9 @@
+package j2k;
+
+public class MixedClass {
+ public void hello() {
+ System.out.println("hello");
+ }
+
+ public static void staticMethod() {}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/simple.after b/contrib/kotlin/src/test/resources/projForTest/src/j2k/simple.after
new file mode 100644
index 0000000..55252d6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/simple.after
@@ -0,0 +1,7 @@
+package j2k
+
+class SimpleClass {
+ fun hello() {
+ System.out.println("hello")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/simple.java b/contrib/kotlin/src/test/resources/projForTest/src/j2k/simple.java
new file mode 100644
index 0000000..a58077d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/simple.java
@@ -0,0 +1,7 @@
+package j2k;
+
+public class SimpleClass {
+ public void hello() {
+ System.out.println("hello");
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/withInnerClass.after b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withInnerClass.after
new file mode 100644
index 0000000..4c38a15
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withInnerClass.after
@@ -0,0 +1,7 @@
+package j2k
+
+class SimpleClass {
+ internal inner class InnerClass {
+ fun doNothing() {}
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/withInnerClass.java b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withInnerClass.java
new file mode 100644
index 0000000..450f4d4
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withInnerClass.java
@@ -0,0 +1,8 @@
+package j2k;
+
+public class SimpleClass {
+ class InnerClass {
+ void doNothing(){
+ }
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/withStaticMethod.after b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withStaticMethod.after
new file mode 100644
index 0000000..c34c3fb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withStaticMethod.after
@@ -0,0 +1,7 @@
+package j2k
+
+object WithStaticClass {
+ fun hello() {
+ System.out.println("hello")
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/j2k/withStaticMethod.java b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withStaticMethod.java
new file mode 100644
index 0000000..fb7f309
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/j2k/withStaticMethod.java
@@ -0,0 +1,7 @@
+package j2k;
+
+public class WithStaticClass {
+ public static void hello() {
+ System.out.println("hello");
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/main/main.kt b/contrib/kotlin/src/test/resources/projForTest/src/main/main.kt
new file mode 100644
index 0000000..e6d1624
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/main/main.kt
@@ -0,0 +1,11 @@
+package main
+
+/*
+
+ @author Alexander.Baratynski
+ Created on Jul 22, 2016
+*/
+
+fun main(args : Array<String>) {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/JavaClass.caret b/contrib/kotlin/src/test/resources/projForTest/src/navigation/JavaClass.caret
new file mode 100644
index 0000000..cd795a5
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/JavaClass.caret
@@ -0,0 +1,5 @@
+package navigation;
+
+<caret>public class JavaClass {
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/JavaClass.java b/contrib/kotlin/src/test/resources/projForTest/src/navigation/JavaClass.java
new file mode 100644
index 0000000..1145493
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/JavaClass.java
@@ -0,0 +1,5 @@
+package navigation;
+
+public class JavaClass {
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/KotlinClass.caret b/contrib/kotlin/src/test/resources/projForTest/src/navigation/KotlinClass.caret
new file mode 100644
index 0000000..5686fe6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/KotlinClass.caret
@@ -0,0 +1,5 @@
+package navigation
+
+class <caret>KotlinClass {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/KotlinClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/navigation/KotlinClass.kt
new file mode 100644
index 0000000..1f8ad9a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/KotlinClass.kt
@@ -0,0 +1,5 @@
+package navigation
+
+class KotlinClass {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToClass.kt
new file mode 100644
index 0000000..1ee196a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToClass.kt
@@ -0,0 +1,5 @@
+package navigation
+
+fun navigateToClass(){
+ <caret>KotlinClass()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToFunction.kt b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToFunction.kt
new file mode 100644
index 0000000..68ba601
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToFunction.kt
@@ -0,0 +1,5 @@
+package navigation
+
+fun checkNavigationToFunction(){
+ <caret>function()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToJavaClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToJavaClass.kt
new file mode 100644
index 0000000..e2c536b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToJavaClass.kt
@@ -0,0 +1,5 @@
+package navigation
+
+fun getJavaClass() {
+ <caret>JavaClass()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToVariable.caret b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToVariable.caret
new file mode 100644
index 0000000..72a2c1f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToVariable.caret
@@ -0,0 +1,11 @@
+package navigation
+
+class SomeKotlinClass {
+
+ val <caret>str = "String"
+
+ fun navigate(){
+ str
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToVariable.kt b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToVariable.kt
new file mode 100644
index 0000000..2773b24
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/checkNavigationToVariable.kt
@@ -0,0 +1,11 @@
+package navigation
+
+class SomeKotlinClass {
+
+ val str = "String"
+
+ fun navigate(){
+ <caret>str
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/functionToNavigate.caret b/contrib/kotlin/src/test/resources/projForTest/src/navigation/functionToNavigate.caret
new file mode 100644
index 0000000..45b071e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/functionToNavigate.caret
@@ -0,0 +1,3 @@
+package navigation
+
+fun <caret>function(){}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/navigation/functionToNavigate.kt b/contrib/kotlin/src/test/resources/projForTest/src/navigation/functionToNavigate.kt
new file mode 100644
index 0000000..60ec767
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/navigation/functionToNavigate.kt
@@ -0,0 +1,3 @@
+package navigation
+
+fun function(){}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/implementMembers.after b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/implementMembers.after
new file mode 100644
index 0000000..ec363b0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/implementMembers.after
@@ -0,0 +1,12 @@
+package quickfixes
+
+class InterfaceImpl : Interface {
+ override fun someFunc(): Int {
+ throw UnsupportedOperationException()
+ }
+
+}
+
+interface Interface {
+ fun someFunc(): Int
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/implementMembers.kt b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/implementMembers.kt
new file mode 100644
index 0000000..cb49a5b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/implementMembers.kt
@@ -0,0 +1,7 @@
+package quickfixes
+
+class InterfaceImpl : Interface
+
+interface Interface {
+ fun someFunc(): Int
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUnnecessaryCall.after b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUnnecessaryCall.after
new file mode 100644
index 0000000..dd675cb
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUnnecessaryCall.after
@@ -0,0 +1,8 @@
+package quickfixes
+
+fun removeUnnecessarySafeCall() {
+ val integer = 42
+ integer.toString()
+}
+
+private fun useOfRemoveUnnecessarySafeCall() = removeUnnecessarySafeCall()
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUnnecessaryCall.kt b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUnnecessaryCall.kt
new file mode 100644
index 0000000..62253b6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUnnecessaryCall.kt
@@ -0,0 +1,8 @@
+package quickfixes
+
+fun removeUnnecessarySafeCall() {
+ val integer = 42
+ integer?.toString()
+}
+
+private fun useOfRemoveUnnecessarySafeCall() = removeUnnecessarySafeCall()
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessCast.after b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessCast.after
new file mode 100644
index 0000000..b0f409c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessCast.after
@@ -0,0 +1,7 @@
+package quickfixes
+
+fun removeUselessCast(integer: Int) {
+ println((integer).toString())
+}
+
+fun useRemoveUselessCast() = removeUselessCast(1)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessCast.kt b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessCast.kt
new file mode 100644
index 0000000..1d42b52
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessCast.kt
@@ -0,0 +1,7 @@
+package quickfixes
+
+fun removeUselessCast(integer: Int) {
+ println((integer as Int).toString())
+}
+
+fun useRemoveUselessCast() = removeUselessCast(1)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessElvis.after b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessElvis.after
new file mode 100644
index 0000000..9863483
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessElvis.after
@@ -0,0 +1,7 @@
+package quickfixes
+
+fun removeUselessElvis(a: Int) {
+ a
+}
+
+fun useRemoveUselessElvis() = removeUselessElvis(1)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessElvis.kt b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessElvis.kt
new file mode 100644
index 0000000..89b606a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/quickfixes/removeUselessElvis.kt
@@ -0,0 +1,7 @@
+package quickfixes
+
+fun removeUselessElvis(a: Int) {
+ a ?: return
+}
+
+fun useRemoveUselessElvis() = removeUselessElvis(1)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.after
new file mode 100644
index 0000000..46e3f6b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.after
@@ -0,0 +1,7 @@
+package rename.classbyconstructor
+
+class KotlinRules
+
+fun main(args: Array<String>) {
+ KotlinRules()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.caret
new file mode 100644
index 0000000..0e24901
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.caret
@@ -0,0 +1,7 @@
+package rename.classbyconstructor
+
+class Kotlin
+
+fun main(args: Array<String>) {
+ <caret>Kotlin()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.kt
new file mode 100644
index 0000000..14d230f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classbyconstructor/file.kt
@@ -0,0 +1,7 @@
+package rename.classbyconstructor
+
+class Kotlin
+
+fun main(args: Array<String>) {
+ Kotlin()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.after
new file mode 100644
index 0000000..f115636
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.after
@@ -0,0 +1,6 @@
+package rename.classrename
+class NewName
+
+fun main(args : Array<String>) {
+ println(NewName().hashCode())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.caret
new file mode 100644
index 0000000..6fd8d47
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.caret
@@ -0,0 +1,6 @@
+package rename.classrename
+class <caret>ClassToRename
+
+fun main(args : Array<String>) {
+ println(ClassToRename().hashCode())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.kt
new file mode 100644
index 0000000..baec3ff
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file.kt
@@ -0,0 +1,6 @@
+package rename.classrename
+class ClassToRename
+
+fun main(args : Array<String>) {
+ println(ClassToRename().hashCode())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file2.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file2.after
new file mode 100644
index 0000000..0c5323a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file2.after
@@ -0,0 +1,3 @@
+package rename.classrename
+
+fun someFunc() = NewName().hashCode()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file2.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file2.kt
new file mode 100644
index 0000000..36c828a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/classrename/file2.kt
@@ -0,0 +1,3 @@
+package rename.classrename
+
+fun someFunc() = ClassToRename().hashCode()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.after
new file mode 100644
index 0000000..dfcceb9
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.after
@@ -0,0 +1,7 @@
+package rename.forloop
+
+fun main(args: Array<String>) {
+ for (arg1 in args) {
+ println(arg1)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.caret
new file mode 100644
index 0000000..033356d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.caret
@@ -0,0 +1,7 @@
+package rename.forloop
+
+fun main(args: Array<String>) {
+ for (arg in args) {
+ println(<caret>arg)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.kt
new file mode 100644
index 0000000..cc5fbf6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop/file.kt
@@ -0,0 +1,7 @@
+package rename.forloop
+
+fun main(args: Array<String>) {
+ for (arg in args) {
+ println(arg)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.after
new file mode 100644
index 0000000..cc5591b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.after
@@ -0,0 +1,9 @@
+package rename.forloop2
+
+val arg = 42
+
+fun main(args: Array<String>) {
+ for (arg1 in args) {
+ println(arg1)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.caret
new file mode 100644
index 0000000..f5eb437
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.caret
@@ -0,0 +1,9 @@
+package rename.forloop2
+
+val arg = 42
+
+fun main(args: Array<String>) {
+ for (<caret>arg in args) {
+ println(arg)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.kt
new file mode 100644
index 0000000..97e95db
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/forloop2/file.kt
@@ -0,0 +1,9 @@
+package rename.forloop2
+
+val arg = 42
+
+fun main(args: Array<String>) {
+ for (arg in args) {
+ println(arg)
+ }
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.after
new file mode 100644
index 0000000..8055d26
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.after
@@ -0,0 +1,7 @@
+package rename.function
+
+class Bar {
+ fun fooFunc() = println("bar")
+}
+
+fun main(args: Array<String>) = Bar().fooFunc()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.caret
new file mode 100644
index 0000000..9818ce4
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.caret
@@ -0,0 +1,7 @@
+package rename.function
+
+class Bar {
+ fun <caret>barFunc() = println("bar")
+}
+
+fun main(args: Array<String>) = Bar().barFunc()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.kt
new file mode 100644
index 0000000..191f82c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/function/file.kt
@@ -0,0 +1,7 @@
+package rename.function
+
+class Bar {
+ fun barFunc() = println("bar")
+}
+
+fun main(args: Array<String>) = Bar().barFunc()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.after
new file mode 100644
index 0000000..0ef8aa7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.after
@@ -0,0 +1,11 @@
+package rename.functionparameter
+
+val someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
+
+fun anotherFun2(someValue: Int) = println(someValue)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.caret
new file mode 100644
index 0000000..bb057f2
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.caret
@@ -0,0 +1,11 @@
+package rename.functionparameter
+
+val someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
+
+fun anotherFun2(<caret>someVal: Int) = println(someVal)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.kt
new file mode 100644
index 0000000..aeef977
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/functionparameter/file.kt
@@ -0,0 +1,11 @@
+package rename.functionparameter
+
+val someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
+
+fun anotherFun2(someVal: Int) = println(someVal)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.after
new file mode 100644
index 0000000..c884052
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.after
@@ -0,0 +1,5 @@
+package rename.methodrename
+
+class ClassWithMethod {
+ fun notSoCoolFun() = println()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.caret
new file mode 100644
index 0000000..994cbed
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.caret
@@ -0,0 +1,5 @@
+package rename.methodrename
+
+class ClassWithMethod {
+ fun <caret>coolFun() = println()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.kt
new file mode 100644
index 0000000..17c7bf0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file.kt
@@ -0,0 +1,5 @@
+package rename.methodrename
+
+class ClassWithMethod {
+ fun coolFun() = println()
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file2.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file2.after
new file mode 100644
index 0000000..3e549fc
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file2.after
@@ -0,0 +1,3 @@
+package rename.methodrename
+
+fun someFunc() = ClassWithMethod().notSoCoolFun()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file2.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file2.kt
new file mode 100644
index 0000000..c011097
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/methodrename/file2.kt
@@ -0,0 +1,3 @@
+package rename.methodrename
+
+fun someFunc() = ClassWithMethod().coolFun()
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.after
new file mode 100644
index 0000000..d7bd466
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.after
@@ -0,0 +1,9 @@
+package rename.properties
+
+val someValue = 5
+
+fun main(args : Array<String>) {
+ println(someValue)
+}
+
+fun anotherFun() = println(someValue)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.caret
new file mode 100644
index 0000000..432bc52
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.caret
@@ -0,0 +1,9 @@
+package rename.properties
+
+val <caret>someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.kt
new file mode 100644
index 0000000..bc79d8f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/properties/file.kt
@@ -0,0 +1,9 @@
+package rename.properties
+
+val someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.after
new file mode 100644
index 0000000..47ebb2d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.after
@@ -0,0 +1,6 @@
+package rename.simple
+class NewName
+
+fun main(args : Array<String>) {
+ println(NewName().hashCode())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.caret
new file mode 100644
index 0000000..b16c68b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.caret
@@ -0,0 +1,6 @@
+package rename.simple
+class <caret>ClassToRename
+
+fun main(args : Array<String>) {
+ println(ClassToRename().hashCode())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.kt
new file mode 100644
index 0000000..eb1cd9e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/simple/file.kt
@@ -0,0 +1,6 @@
+package rename.simple
+class ClassToRename
+
+fun main(args : Array<String>) {
+ println(ClassToRename().hashCode())
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.after b/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.after
new file mode 100644
index 0000000..7d588f2
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.after
@@ -0,0 +1,11 @@
+package rename.simplesec
+
+val someValue = 5
+
+fun main(args : Array<String>) {
+ println(someValue)
+}
+
+fun anotherFun() = println(someValue)
+
+fun anotherFun2(someVal: Int) = println(someVal)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.caret b/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.caret
new file mode 100644
index 0000000..9388302
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.caret
@@ -0,0 +1,11 @@
+package rename.simplesec
+
+val <caret>someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
+
+fun anotherFun2(someVal: Int) = println(someVal)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.kt b/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.kt
new file mode 100644
index 0000000..cf72a2e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/rename/simplesec/file.kt
@@ -0,0 +1,11 @@
+package rename.simplesec
+
+val someVal = 5
+
+fun main(args : Array<String>) {
+ println(someVal)
+}
+
+fun anotherFun() = println(someVal)
+
+fun anotherFun2(someVal: Int) = println(someVal)
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/annotation.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/annotation.caret
new file mode 100644
index 0000000..101d734
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/annotation.caret
@@ -0,0 +1,4 @@
+package semantic
+
+<caret>@Deprecated<caret>("deprecated")
+fun deprecatedFun() = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/annotation.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/annotation.kt
new file mode 100644
index 0000000..46d5997
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/annotation.kt
@@ -0,0 +1,4 @@
+package semantic
+
+@Deprecated("deprecated")
+fun deprecatedFun() = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/class.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/class.caret
new file mode 100644
index 0000000..add9fea
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/class.caret
@@ -0,0 +1,7 @@
+package semantic
+
+class <caret>SomeClass<caret> {
+
+ val <caret>value<caret> = 42
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/class.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/class.kt
new file mode 100644
index 0000000..2da7780
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/class.kt
@@ -0,0 +1,7 @@
+package semantic
+
+class SomeClass {
+
+ val value = 42
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/deprecated.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/deprecated.caret
new file mode 100644
index 0000000..f808aea
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/deprecated.caret
@@ -0,0 +1,3 @@
+package semantic
+
+fun useDeprecated() = <caret>deprecatedFun<caret>()
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/deprecated.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/deprecated.kt
new file mode 100644
index 0000000..69fed90
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/deprecated.kt
@@ -0,0 +1,3 @@
+package semantic
+
+fun useDeprecated() = deprecatedFun()
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/empty.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/empty.caret
new file mode 100644
index 0000000..e65446f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/empty.caret
@@ -0,0 +1 @@
+package semantic
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/empty.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/empty.kt
new file mode 100644
index 0000000..e65446f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/empty.kt
@@ -0,0 +1 @@
+package semantic
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/functionWithLocalVariables.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/functionWithLocalVariables.caret
new file mode 100644
index 0000000..a3d3ad4
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/functionWithLocalVariables.caret
@@ -0,0 +1,6 @@
+package semantic
+
+fun <caret>functionWithLocalVariables<caret>() {
+ val <caret>value<caret> = 0
+ var <caret>variable<caret> = 0
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/functionWithLocalVariables.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/functionWithLocalVariables.kt
new file mode 100644
index 0000000..87b0479
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/functionWithLocalVariables.kt
@@ -0,0 +1,6 @@
+package semantic
+
+fun functionWithLocalVariables() {
+ val value = 0
+ var variable = 0
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/simpleClass.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/simpleClass.caret
new file mode 100644
index 0000000..dbbbf54
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/simpleClass.caret
@@ -0,0 +1,6 @@
+package semantic
+
+class <caret>SemClass<caret> {
+
+}
+
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/simpleClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/simpleClass.kt
new file mode 100644
index 0000000..768b6ea
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/simpleClass.kt
@@ -0,0 +1,5 @@
+package semantic
+
+class SemClass {
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/smartCast.caret b/contrib/kotlin/src/test/resources/projForTest/src/semantic/smartCast.caret
new file mode 100644
index 0000000..7ce7c53
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/smartCast.caret
@@ -0,0 +1,8 @@
+package semantic
+
+private fun getNumber(bool: Boolean): Int? = if (bool) 42 else null
+
+fun testSmartCastHighlighting() {
+ val value = getNumber(false)
+ if (value != null) <caret>value<caret> + 1
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/semantic/smartCast.kt b/contrib/kotlin/src/test/resources/projForTest/src/semantic/smartCast.kt
new file mode 100644
index 0000000..a83c35e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/semantic/smartCast.kt
@@ -0,0 +1,8 @@
+package semantic
+
+private fun getNumber(bool: Boolean): Int? = if (bool) 42 else null
+
+fun testSmartCastHighlighting() {
+ val value = getNumber(false)
+ if (value != null) value + 1
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/classWithSeveralMembers.kt b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/classWithSeveralMembers.kt
new file mode 100644
index 0000000..6b0af63
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/classWithSeveralMembers.kt
@@ -0,0 +1,10 @@
+package structureScanner
+
+class ClassWithSeveralMembers {
+
+ private val member = 42
+
+ fun member() = 42
+
+ class InnerClass
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/empty.kt b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/empty.kt
new file mode 100644
index 0000000..07d41a9
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/empty.kt
@@ -0,0 +1 @@
+package structureScanner
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/object.kt b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/object.kt
new file mode 100644
index 0000000..6b67965
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/object.kt
@@ -0,0 +1,5 @@
+package structureScanner
+
+object Obj {
+ fun hello() = "Hello"
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/severalClasses.kt b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/severalClasses.kt
new file mode 100644
index 0000000..75b6dae
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/severalClasses.kt
@@ -0,0 +1,29 @@
+package structureScanner
+
+class FirstClass {
+
+ private val prop = 42
+
+ private val prop2 = 1
+
+ private fun method() = prop + prop2
+
+ class InnerClass {
+
+ fun hi() = "hi"
+
+ class InnerInnerClass {
+
+ private val INNER = 42
+
+ }
+
+ }
+
+}
+
+object SecondObject {
+
+ fun ft() = 42
+
+}
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/severalFunctions.kt b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/severalFunctions.kt
new file mode 100644
index 0000000..e73f873
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/severalFunctions.kt
@@ -0,0 +1,5 @@
+package structureScanner
+
+fun first() = 42
+
+fun second() = 42
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/simple.kt b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/simple.kt
new file mode 100644
index 0000000..a668302
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/structureScanner/simple.kt
@@ -0,0 +1,3 @@
+package structureScanner
+
+fun simple() = 1
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/FirstClass.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/FirstClass.after
new file mode 100644
index 0000000..f81368e
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/FirstClass.after
@@ -0,0 +1,4 @@
+package stubGen;
+public final class FirstClass extends java.lang.Object {
+public FirstClass(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/SecondClass.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/SecondClass.after
new file mode 100644
index 0000000..1846619
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/SecondClass.after
@@ -0,0 +1,4 @@
+package stubGen;
+public final class SecondClass extends java.lang.Object {
+public SecondClass(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/abstractClass.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/abstractClass.after
new file mode 100644
index 0000000..1149813
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/abstractClass.after
@@ -0,0 +1,4 @@
+package stubGen;
+public abstract class SimpleAbstractClass extends java.lang.Object {
+public SimpleAbstractClass(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/abstractClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/abstractClass.kt
new file mode 100644
index 0000000..c035207
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/abstractClass.kt
@@ -0,0 +1,4 @@
+package stubGen
+
+abstract class SimpleAbstractClass {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithTypeParameter.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithTypeParameter.after
new file mode 100644
index 0000000..07ff27d
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithTypeParameter.after
@@ -0,0 +1,4 @@
+package stubGen;
+public final class ClassWithTypeParameter <T extends java.lang.CharSequence> {
+public ClassWithTypeParameter(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithTypeParameter.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithTypeParameter.kt
new file mode 100644
index 0000000..792963c
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithTypeParameter.kt
@@ -0,0 +1,5 @@
+package stubGen
+
+class ClassWithTypeParameter<T : CharSequence> {
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVal.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVal.after
new file mode 100644
index 0000000..f04dc73
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVal.after
@@ -0,0 +1,6 @@
+package stubGen;
+public final class ClassWithVal extends java.lang.Object {
+ private final java.lang.String prop;
+ public final java.lang.String getProp(){}
+ public ClassWithVal(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVal.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVal.kt
new file mode 100644
index 0000000..2064534
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVal.kt
@@ -0,0 +1,5 @@
+package stubGen
+
+class ClassWithVal {
+ val prop = "str"
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVar.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVar.after
new file mode 100644
index 0000000..cf46620
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVar.after
@@ -0,0 +1,7 @@
+package stubGen;
+public final class ClassWithVar extends java.lang.Object {
+ private java.lang.String prop;
+ public final java.lang.String getProp(){}
+ public final void setProp(java.lang.String a0){}
+ public ClassWithVar(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVar.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVar.kt
new file mode 100644
index 0000000..d659342
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/classWithVar.kt
@@ -0,0 +1,5 @@
+package stubGen
+
+class ClassWithVar {
+ var prop = "str"
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/enum.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/enum.after
new file mode 100644
index 0000000..297c777
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/enum.after
@@ -0,0 +1,5 @@
+package stubGen;
+public enum SimpleEnum extends java.lang.Enum<stubGen.SimpleEnum>{ ONE, TWO, THREE;protected SimpleEnum(){}
+ public static stubGen.SimpleEnum[] values(){}
+ public static stubGen.SimpleEnum valueOf(java.lang.String a0){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/enum.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/enum.kt
new file mode 100644
index 0000000..6be9624
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/enum.kt
@@ -0,0 +1,5 @@
+package stubGen
+
+enum class SimpleEnum {
+ ONE, TWO, THREE
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface.kt
new file mode 100644
index 0000000..66be74f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface.kt
@@ -0,0 +1,6 @@
+package stubGen
+
+interface Interface
+
+class SimpleImplements : Interface {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface1.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface1.after
new file mode 100644
index 0000000..f9d462a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface1.after
@@ -0,0 +1,3 @@
+package stubGen;
+public interface Interface {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface2.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface2.after
new file mode 100644
index 0000000..0c436fa
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/implementsInterface2.after
@@ -0,0 +1,4 @@
+package stubGen;
+public final class SimpleImplements extends java.lang.Object implements stubGen.Interface {
+public SimpleImplements(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/interface.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/interface.after
new file mode 100644
index 0000000..b86b62f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/interface.after
@@ -0,0 +1,3 @@
+package stubGen;
+public interface SimpleInterface {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/interface.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/interface.kt
new file mode 100644
index 0000000..d0e1ede
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/interface.kt
@@ -0,0 +1,4 @@
+package stubGen
+
+interface SimpleInterface {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/object.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/object.after
new file mode 100644
index 0000000..4f3d4e7
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/object.after
@@ -0,0 +1,5 @@
+package stubGen;
+public final class SimpleObject extends java.lang.Object {
+ public final static stubGen.SimpleObject INSTANCE;
+ private SimpleObject(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/object.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/object.kt
new file mode 100644
index 0000000..4aabbb6
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/object.kt
@@ -0,0 +1,4 @@
+package stubGen
+
+object SimpleObject {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/openClass.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/openClass.after
new file mode 100644
index 0000000..a31aa33
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/openClass.after
@@ -0,0 +1,4 @@
+package stubGen;
+public class SimpleOpenClass extends java.lang.Object {
+public SimpleOpenClass(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/openClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/openClass.kt
new file mode 100644
index 0000000..c40f17a
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/openClass.kt
@@ -0,0 +1,4 @@
+package stubGen
+
+open class SimpleOpenClass {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalArguments.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalArguments.after
new file mode 100644
index 0000000..d286e97
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalArguments.after
@@ -0,0 +1,5 @@
+package stubGen;
+public final class SeveralArguments extends java.lang.Object {
+public final void func(java.lang.String a0, java.lang.String a1){}
+public SeveralArguments(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalArguments.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalArguments.kt
new file mode 100644
index 0000000..438a10b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalArguments.kt
@@ -0,0 +1,7 @@
+package stubGen
+
+class SeveralArguments {
+
+fun func(a0: String, a1: String){}
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalClassesInOneFile.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalClassesInOneFile.kt
new file mode 100644
index 0000000..f6c6fe0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/severalClassesInOneFile.kt
@@ -0,0 +1,7 @@
+package stubGen
+
+class FirstClass {
+}
+
+class SecondClass {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/simple.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/simple.after
new file mode 100644
index 0000000..bf08b2f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/simple.after
@@ -0,0 +1,4 @@
+package stubGen;
+public final class Simple extends java.lang.Object {
+public Simple(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/simple.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/simple.kt
new file mode 100644
index 0000000..d7eb289
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/simple.kt
@@ -0,0 +1,4 @@
+package stubGen
+
+class Simple {
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withCompanion.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withCompanion.after
new file mode 100644
index 0000000..3ffa81b
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withCompanion.after
@@ -0,0 +1,9 @@
+package stubGen;
+public final class WithCompanion extends java.lang.Object {
+public final static stubGen.WithCompanion.Companion Companion;
+public WithCompanion(){}
+public final static class Companion extends java.lang.Object {
+ public final java.lang.String hello(){}
+ private Companion(){}
+}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withCompanion.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withCompanion.kt
new file mode 100644
index 0000000..1584fe3
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withCompanion.kt
@@ -0,0 +1,9 @@
+package stubGen
+
+class WithCompanion {
+
+ companion object {
+ fun hello() = "hello"
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withNestedClass.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withNestedClass.after
new file mode 100644
index 0000000..9eaf003
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withNestedClass.after
@@ -0,0 +1,9 @@
+package stubGen;
+public final class ClassWithNestedClass extends java.lang.Object {
+ public ClassWithNestedClass(){}
+
+ public final static class Nested extends java.lang.Object {
+ public Nested(){}
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withNestedClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withNestedClass.kt
new file mode 100644
index 0000000..ab75d93
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withNestedClass.kt
@@ -0,0 +1,8 @@
+package stubGen
+
+class ClassWithNestedClass {
+
+ class Nested {
+ }
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withSeveralMethods.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withSeveralMethods.after
new file mode 100644
index 0000000..e91e855
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withSeveralMethods.after
@@ -0,0 +1,7 @@
+package stubGen;
+public final class ClassWithSeveralMethods extends java.lang.Object {
+public final void firstMethod(){}
+public final void secondMethod(){}
+public final void thirdMethod(){}
+public ClassWithSeveralMethods(){}
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withSeveralMethods.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withSeveralMethods.kt
new file mode 100644
index 0000000..4e8bbdf
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withSeveralMethods.kt
@@ -0,0 +1,9 @@
+package stubGen
+
+class ClassWithSeveralMethods {
+
+ fun firstMethod(){}
+ fun secondMethod(){}
+ fun thirdMethod(){}
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withoutClass.after b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withoutClass.after
new file mode 100644
index 0000000..5c682f0
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withoutClass.after
@@ -0,0 +1,5 @@
+package stubGen;
+public final class WithoutClassKt extends java.lang.Object {
+ public final static void hello() {}
+
+}
\ No newline at end of file
diff --git a/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withoutClass.kt b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withoutClass.kt
new file mode 100644
index 0000000..9cbe67f
--- /dev/null
+++ b/contrib/kotlin/src/test/resources/projForTest/src/stubGen/withoutClass.kt
@@ -0,0 +1,3 @@
+package stubGen
+
+fun hello() = println("Hello")
\ No newline at end of file