mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-22 08:31:31 +00:00
Compare commits
249 Commits
native-ann
...
M12/bootst
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45528e2e8e | ||
|
|
72429f7b1c | ||
|
|
99c7ab75c4 | ||
|
|
e1131b4e78 | ||
|
|
9b074d490d | ||
|
|
e4f6d8589a | ||
|
|
34acef25f5 | ||
|
|
188e85c6b1 | ||
|
|
b5f7ccfb84 | ||
|
|
adb4817fc0 | ||
|
|
94e827747e | ||
|
|
65269976c7 | ||
|
|
18b6a7f741 | ||
|
|
1ffdeff757 | ||
|
|
c9057704eb | ||
|
|
928769e714 | ||
|
|
a3b7be4c1a | ||
|
|
6801d8a672 | ||
|
|
31e63fed1d | ||
|
|
b622f332e4 | ||
|
|
fc97978ac8 | ||
|
|
200638c84d | ||
|
|
7fa59d49bd | ||
|
|
e86ac42b89 | ||
|
|
cf19b7ad5f | ||
|
|
556aea8d6b | ||
|
|
e549376368 | ||
|
|
82ce60f5c7 | ||
|
|
e8a475973b | ||
|
|
d016c40ea4 | ||
|
|
4d0e7d3b28 | ||
|
|
f3fed44d66 | ||
|
|
bbf5c575c2 | ||
|
|
b7267b7fe9 | ||
|
|
0f8b636bc5 | ||
|
|
c893df200d | ||
|
|
d4b8139a7f | ||
|
|
4800147f4e | ||
|
|
9fcfb6a823 | ||
|
|
58867d5500 | ||
|
|
b739794c3e | ||
|
|
5135e24bd1 | ||
|
|
97805ce031 | ||
|
|
60d5559d44 | ||
|
|
d790ea9604 | ||
|
|
a7cac634fc | ||
|
|
097b82084c | ||
|
|
1a809eafae | ||
|
|
1ed1772e6c | ||
|
|
cd06178dda | ||
|
|
33ed77e87b | ||
|
|
00b57b6fbf | ||
|
|
8758898386 | ||
|
|
b9207a7e8b | ||
|
|
2a3523fbaa | ||
|
|
ea7496294c | ||
|
|
8085303783 | ||
|
|
f4277c9d9e | ||
|
|
02ec7a152e | ||
|
|
9f836e8151 | ||
|
|
19c3ab4487 | ||
|
|
14fdad27d8 | ||
|
|
9e7544518c | ||
|
|
a1c5cef667 | ||
|
|
e3b8ed3b49 | ||
|
|
7303d18568 | ||
|
|
f475a7f7cf | ||
|
|
1f1496c516 | ||
|
|
70d627e972 | ||
|
|
5fa8ccca66 | ||
|
|
63276e36fc | ||
|
|
1b1affd7ac | ||
|
|
ff631643aa | ||
|
|
b418288acd | ||
|
|
7351880a19 | ||
|
|
2ef90cff80 | ||
|
|
e7d2157429 | ||
|
|
8353a78167 | ||
|
|
23835c7c65 | ||
|
|
ac6e159f4c | ||
|
|
72e1202579 | ||
|
|
eec2aff821 | ||
|
|
04d81a7c35 | ||
|
|
6e7f6b2bcf | ||
|
|
aada36905c | ||
|
|
bb56a2a587 | ||
|
|
0806e947e8 | ||
|
|
b88b8f5f43 | ||
|
|
989591043f | ||
|
|
c38180601a | ||
|
|
e710fe9b24 | ||
|
|
f9750e60f3 | ||
|
|
3d37154e2c | ||
|
|
38c693d47d | ||
|
|
91eeb9c3fd | ||
|
|
6e302f6453 | ||
|
|
e129306641 | ||
|
|
3224df4f7e | ||
|
|
4375ed28a4 | ||
|
|
70ae2f319e | ||
|
|
8ab09c9bbe | ||
|
|
8ef4b3e6bc | ||
|
|
c3d96fb58a | ||
|
|
46b8ec7ebb | ||
|
|
c4ed9861fe | ||
|
|
1853d79076 | ||
|
|
a8056a67a4 | ||
|
|
64501a2198 | ||
|
|
d76542fad4 | ||
|
|
6c27a1d0b3 | ||
|
|
191287fc1e | ||
|
|
23786caf32 | ||
|
|
a9663fa2b5 | ||
|
|
1a16e3cdeb | ||
|
|
f939640407 | ||
|
|
a6f872a75d | ||
|
|
739cb9ff7c | ||
|
|
d8df392542 | ||
|
|
940445fd88 | ||
|
|
c3615b14be | ||
|
|
8ba465f3a8 | ||
|
|
0f7cf8bd41 | ||
|
|
a4dc23535c | ||
|
|
18668b8409 | ||
|
|
6ae3a5806e | ||
|
|
96f0c1c215 | ||
|
|
e3df2d0056 | ||
|
|
7e24413e9b | ||
|
|
f2caacd57f | ||
|
|
b6c84cf584 | ||
|
|
c1707058f2 | ||
|
|
18c3a7651e | ||
|
|
68f1d402b3 | ||
|
|
1f1234aa73 | ||
|
|
b60798f8d0 | ||
|
|
ed7b69cce0 | ||
|
|
90cf9d6f6f | ||
|
|
c0b0076c70 | ||
|
|
5f831c3855 | ||
|
|
617f8da9d4 | ||
|
|
064b285145 | ||
|
|
56a8142116 | ||
|
|
06ad3a35ae | ||
|
|
cd7bc58904 | ||
|
|
024fb4a54a | ||
|
|
02cc792b3c | ||
|
|
5b1375d427 | ||
|
|
7b1782111b | ||
|
|
45884c436d | ||
|
|
3bf15229ca | ||
|
|
5018be1b86 | ||
|
|
2f53c2cd4f | ||
|
|
3362c967e7 | ||
|
|
291ace122f | ||
|
|
169067be6b | ||
|
|
ac1b5bba22 | ||
|
|
729c171013 | ||
|
|
a86e263cfe | ||
|
|
6a0eb98734 | ||
|
|
9405f76875 | ||
|
|
ad13fbb119 | ||
|
|
48db830501 | ||
|
|
2c8d32fa84 | ||
|
|
3190df86a5 | ||
|
|
7176f8c116 | ||
|
|
14c116d2d5 | ||
|
|
a272b48be4 | ||
|
|
7283bf39dd | ||
|
|
4bf306b754 | ||
|
|
512d671ea0 | ||
|
|
51b2d9a15e | ||
|
|
c5e47d9ebf | ||
|
|
50028b203c | ||
|
|
d945388d88 | ||
|
|
ffd367613c | ||
|
|
af98c00558 | ||
|
|
d893fe7655 | ||
|
|
a15a5d7b74 | ||
|
|
37f6009fdd | ||
|
|
299d429407 | ||
|
|
ca11ef3968 | ||
|
|
5094d74496 | ||
|
|
74464f2fef | ||
|
|
73f178185c | ||
|
|
6f1f82e5cb | ||
|
|
edf030d1b7 | ||
|
|
12eaf709e8 | ||
|
|
dd6f1a24e6 | ||
|
|
322d7b2e43 | ||
|
|
7500181abb | ||
|
|
4f69f658be | ||
|
|
5915863a40 | ||
|
|
85ab17841e | ||
|
|
6532613aa0 | ||
|
|
d2bba0c8b9 | ||
|
|
21d102e667 | ||
|
|
258e8300ea | ||
|
|
40f8b5a025 | ||
|
|
29398f2150 | ||
|
|
d7e40fb06c | ||
|
|
becb75dcc7 | ||
|
|
88091ff555 | ||
|
|
e3f7f9402f | ||
|
|
754f82296c | ||
|
|
41b9d10782 | ||
|
|
abce9e0304 | ||
|
|
3c78547b67 | ||
|
|
b5f8f55cf4 | ||
|
|
18848afe2c | ||
|
|
0252137b0b | ||
|
|
53945d88e7 | ||
|
|
e1ff588f6c | ||
|
|
b972aac300 | ||
|
|
5c346effe8 | ||
|
|
590e2cceea | ||
|
|
539458c596 | ||
|
|
7f0a5d4fe2 | ||
|
|
b6789e03f4 | ||
|
|
9bac98e906 | ||
|
|
e978221c5e | ||
|
|
ced1f6662c | ||
|
|
8f1176413c | ||
|
|
400fae3053 | ||
|
|
032a9a20cd | ||
|
|
60356ba15d | ||
|
|
517ae669e9 | ||
|
|
df48447009 | ||
|
|
7b46abd43f | ||
|
|
b8f80f21b2 | ||
|
|
3c95349019 | ||
|
|
4898cd0419 | ||
|
|
8470ad48dc | ||
|
|
11c988dabc | ||
|
|
c7f28d30c0 | ||
|
|
f87e2cd2c5 | ||
|
|
35ae6b4941 | ||
|
|
846cfe4531 | ||
|
|
c7669d31dd | ||
|
|
01c6ced2f8 | ||
|
|
54f76c8d3e | ||
|
|
9377e6b914 | ||
|
|
78847a961e | ||
|
|
f996476000 | ||
|
|
9bcc9fbddc | ||
|
|
3de3c0fb88 | ||
|
|
e40fa4da95 | ||
|
|
7b04b939aa | ||
|
|
992a174dea | ||
|
|
50aae7b49e |
1
.idea/artifacts/KotlinPlugin.xml
generated
1
.idea/artifacts/KotlinPlugin.xml
generated
@@ -42,7 +42,6 @@
|
||||
<element id="module-output" name="serialization" />
|
||||
<element id="module-output" name="idea-completion" />
|
||||
<element id="module-output" name="idea-core" />
|
||||
<element id="module-output" name="annotation-collector" />
|
||||
<element id="module-output" name="idea-js" />
|
||||
</element>
|
||||
<element id="library" level="project" name="javax.inject" />
|
||||
|
||||
1
.idea/codeStyleSettings.xml
generated
1
.idea/codeStyleSettings.xml
generated
@@ -270,7 +270,6 @@
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
</indentOptions>
|
||||
|
||||
14
.idea/libraries/ant.xml
generated
Normal file
14
.idea/libraries/ant.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<component name="libraryTable">
|
||||
<library name="ant">
|
||||
<ANNOTATIONS>
|
||||
<root url="file://$PROJECT_DIR$/annotations" />
|
||||
</ANNOTATIONS>
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/ant-1.8/lib/ant.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.8.2-src.zip!/apache-ant-1.8.2/src/main" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
21
.idea/libraries/ant_1_7.xml
generated
21
.idea/libraries/ant_1_7.xml
generated
@@ -1,21 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="ant-1.7">
|
||||
<ANNOTATIONS>
|
||||
<root url="file://$PROJECT_DIR$/annotations" />
|
||||
</ANNOTATIONS>
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/ant-1.7/lib/ant.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/core/loaderref/src" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/core/containersrc" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/types/assertions" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/taskdefs/apt" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/taskdefs/rmic/src" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/taskdefs/fixcrlf/input" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/etc/testcases/taskdefs/fixcrlf/expected" />
|
||||
<root url="jar://$PROJECT_DIR$/dependencies/apache-ant-1.7.0-src.zip!/apache-ant-1.7.0/src/main" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
2
.idea/runConfigurations/All_Tests.xml
generated
2
.idea/runConfigurations/All_Tests.xml
generated
@@ -13,7 +13,7 @@
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="package" />
|
||||
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx900m -XX:MaxPermSize=320m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=64m" />
|
||||
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx900m -XX:MaxPermSize=400m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=128m" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="ant-1.7" level="project" />
|
||||
<orderEntry type="library" name="ant" level="project" />
|
||||
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||
<orderEntry type="module" module-name="preloader" />
|
||||
</component>
|
||||
|
||||
66
ant/src/org/jetbrains/kotlin/ant/KotlinAntTaskUtil.kt
Normal file
66
ant/src/org/jetbrains/kotlin/ant/KotlinAntTaskUtil.kt
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.ant
|
||||
|
||||
import org.apache.tools.ant.AntClassLoader
|
||||
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
|
||||
import java.io.File
|
||||
import java.lang.ref.SoftReference
|
||||
import java.net.JarURLConnection
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
object KotlinAntTaskUtil {
|
||||
private var classLoaderRef = SoftReference<ClassLoader?>(null)
|
||||
|
||||
private val libPath: File by Delegates.lazy {
|
||||
// Find path of kotlin-ant.jar in the filesystem and find kotlin-compiler.jar in the same directory
|
||||
val resourcePath = "/" + javaClass.getName().replace('.', '/') + ".class"
|
||||
val jarConnection = javaClass.getResource(resourcePath).openConnection() as? JarURLConnection
|
||||
?: throw UnsupportedOperationException("Kotlin compiler Ant task should be loaded from the JAR file")
|
||||
val antTaskJarPath = File(jarConnection.getJarFileURL().toURI())
|
||||
|
||||
antTaskJarPath.getParentFile()
|
||||
}
|
||||
|
||||
val compilerJar: File by Delegates.lazy {
|
||||
File(libPath, "kotlin-compiler.jar").assertExists()
|
||||
}
|
||||
|
||||
val runtimeJar: File by Delegates.lazy {
|
||||
File(libPath, "kotlin-runtime.jar").assertExists()
|
||||
}
|
||||
|
||||
private fun File.assertExists(): File {
|
||||
if (!this.exists()) {
|
||||
throw IllegalStateException("${getName()} is not found in the directory of Kotlin Ant task")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
synchronized fun getOrCreateClassLoader(): ClassLoader {
|
||||
val cached = classLoaderRef.get()
|
||||
if (cached != null) return cached
|
||||
|
||||
val myLoader = javaClass.getClassLoader()
|
||||
if (myLoader !is AntClassLoader) return myLoader
|
||||
|
||||
val classLoader = ClassPreloadingUtils.preloadClasses(listOf(compilerJar), 4096, myLoader, null)
|
||||
classLoaderRef = SoftReference(classLoader)
|
||||
|
||||
return classLoader
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,29 @@
|
||||
|
||||
package org.jetbrains.kotlin.ant;
|
||||
|
||||
import kotlin.KotlinPackage;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.MagicNames;
|
||||
import org.apache.tools.ant.taskdefs.Javac;
|
||||
import org.apache.tools.ant.taskdefs.compilers.DefaultCompilerAdapter;
|
||||
import org.apache.tools.ant.taskdefs.compilers.Javac13;
|
||||
import org.apache.tools.ant.taskdefs.condition.AntVersion;
|
||||
import org.apache.tools.ant.types.Commandline;
|
||||
import org.apache.tools.ant.types.Path;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.tools.ant.Project.MSG_WARN;
|
||||
|
||||
public class KotlinCompilerAdapter extends Javac13 {
|
||||
private static final List<String> KOTLIN_EXTENSIONS = Arrays.asList("kt", "kts");
|
||||
|
||||
public class KotlinCompilerAdapter extends DefaultCompilerAdapter {
|
||||
private Path externalAnnotations;
|
||||
public List<Commandline.Argument> additionalArguments = new ArrayList<Commandline.Argument>(0);
|
||||
|
||||
public void setExternalAnnotations(Path externalAnnotations) {
|
||||
this.externalAnnotations = externalAnnotations;
|
||||
@@ -36,22 +51,93 @@ public class KotlinCompilerAdapter extends DefaultCompilerAdapter {
|
||||
return externalAnnotations.createPath();
|
||||
}
|
||||
|
||||
public Commandline.Argument createCompilerArg() {
|
||||
Commandline.Argument argument = new Commandline.Argument();
|
||||
additionalArguments.add(argument);
|
||||
return argument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedFileExtensions() {
|
||||
List<String> result = KotlinPackage.plus(Arrays.asList(super.getSupportedFileExtensions()), KOTLIN_EXTENSIONS);
|
||||
//noinspection SSBasedInspection
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute() throws BuildException {
|
||||
Javac javac = getJavac();
|
||||
|
||||
Kotlin2JvmTask kotlinTask = new Kotlin2JvmTask();
|
||||
kotlinTask.setOutput(javac.getDestdir());
|
||||
kotlinTask.setClasspath(javac.getClasspath());
|
||||
kotlinTask.setSrc(javac.getSrcdir());
|
||||
kotlinTask.setExternalAnnotations(externalAnnotations);
|
||||
checkAntVersion();
|
||||
|
||||
kotlinTask.execute();
|
||||
Kotlin2JvmTask kotlinc = new Kotlin2JvmTask();
|
||||
kotlinc.setFailOnError(javac.getFailonerror());
|
||||
kotlinc.setOutput(javac.getDestdir());
|
||||
|
||||
Path classpath = javac.getClasspath();
|
||||
if (classpath != null) {
|
||||
kotlinc.setClasspath(classpath);
|
||||
}
|
||||
|
||||
// We use the provided src dir instead of compileList, because the latter is insane:
|
||||
// it is constructed only of sources which are newer than classes with the same name
|
||||
kotlinc.setSrc(javac.getSrcdir());
|
||||
|
||||
kotlinc.setExternalAnnotations(externalAnnotations);
|
||||
|
||||
kotlinc.getAdditionalArguments().addAll(additionalArguments);
|
||||
|
||||
kotlinc.execute();
|
||||
if (!Integer.valueOf(0).equals(kotlinc.getExitCode())) {
|
||||
// Don't run javac if failOnError = false and there were errors on Kotlin sources
|
||||
return false;
|
||||
}
|
||||
|
||||
javac.log("Running javac...");
|
||||
|
||||
Javac13 javac13 = new Javac13();
|
||||
javac13.setJavac(javac);
|
||||
return javac13.execute();
|
||||
// Javac13#execute passes everything in compileList to javac, which doesn't recognize .kt files
|
||||
compileList = filterOutKotlinSources(compileList);
|
||||
|
||||
addRuntimeToJavacClasspath(kotlinc);
|
||||
|
||||
return compileList.length == 0 || super.execute();
|
||||
}
|
||||
|
||||
private void addRuntimeToJavacClasspath(@NotNull Kotlin2JvmTask kotlinc) {
|
||||
for (String arg : kotlinc.getArgs()) {
|
||||
// If "-no-stdlib" was specified explicitly, probably the user also wanted the javac classpath to not have it
|
||||
if ("-no-stdlib".equals(arg)) return;
|
||||
}
|
||||
|
||||
if (compileClasspath == null) {
|
||||
compileClasspath = new Path(getProject());
|
||||
}
|
||||
compileClasspath.add(new Path(getProject(), KotlinAntTaskUtil.INSTANCE$.getRuntimeJar().getAbsolutePath()));
|
||||
}
|
||||
|
||||
private void checkAntVersion() {
|
||||
AntVersion checkVersion = new AntVersion();
|
||||
checkVersion.setAtLeast("1.8.2");
|
||||
if (!checkVersion.eval()) {
|
||||
getJavac().log("<withKotlin> task requires Ant of version at least 1.8.2 to operate reliably. " +
|
||||
"Please upgrade or, as a workaround, make sure you have at least one Java source and " +
|
||||
"the output directory is clean before running this task. " +
|
||||
"You have: " + getProject().getProperty(MagicNames.ANT_VERSION), MSG_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static File[] filterOutKotlinSources(@NotNull File[] files) {
|
||||
List<File> nonKotlinSources = KotlinPackage.filterNot(files, new Function1<File, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(File file) {
|
||||
for (String extension : KOTLIN_EXTENSIONS) {
|
||||
if (file.getPath().endsWith("." + extension)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return nonKotlinSources.toArray(new File[nonKotlinSources.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,45 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.ant
|
||||
|
||||
import org.apache.tools.ant.BuildException
|
||||
import org.apache.tools.ant.Task
|
||||
import org.apache.tools.ant.types.Commandline
|
||||
import org.apache.tools.ant.types.Path
|
||||
import org.apache.tools.ant.types.Reference
|
||||
import java.io.File
|
||||
import org.apache.tools.ant.BuildException
|
||||
import org.apache.tools.ant.types.Commandline
|
||||
import java.io.PrintStream
|
||||
import org.apache.tools.ant.AntClassLoader
|
||||
import java.lang.ref.SoftReference
|
||||
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
|
||||
import java.net.JarURLConnection
|
||||
|
||||
object CompilerClassLoaderHolder {
|
||||
private var classLoaderRef = SoftReference<ClassLoader?>(null)
|
||||
|
||||
synchronized fun getOrCreateClassLoader(): ClassLoader {
|
||||
val cached = classLoaderRef.get()
|
||||
if (cached != null) return cached
|
||||
|
||||
val myLoader = javaClass.getClassLoader()
|
||||
if (myLoader !is AntClassLoader) return myLoader
|
||||
|
||||
// Find path of kotlin-ant.jar in the filesystem and find kotlin-compiler.jar in the same directory
|
||||
val resourcePath = "/" + javaClass.getName().replace('.', '/') + ".class"
|
||||
val jarConnection = javaClass.getResource(resourcePath).openConnection() as? JarURLConnection
|
||||
?: throw UnsupportedOperationException("Kotlin compiler Ant task should be loaded from the JAR file")
|
||||
val antTaskJarPath = File(jarConnection.getJarFileURL().toURI())
|
||||
|
||||
val compilerJarPath = File(antTaskJarPath.getParent(), "kotlin-compiler.jar")
|
||||
if (!compilerJarPath.exists()) {
|
||||
throw IllegalStateException("kotlin-compiler.jar is not found in the directory of Kotlin Ant task")
|
||||
}
|
||||
|
||||
val classLoader = ClassPreloadingUtils.preloadClasses(listOf(compilerJarPath), 4096, myLoader, null)
|
||||
classLoaderRef = SoftReference(classLoader)
|
||||
|
||||
return classLoader
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class KotlinCompilerBaseTask : Task() {
|
||||
protected abstract val compilerFqName: String
|
||||
@@ -66,11 +34,14 @@ public abstract class KotlinCompilerBaseTask : Task() {
|
||||
public var nowarn: Boolean = false
|
||||
public var verbose: Boolean = false
|
||||
public var printVersion: Boolean = false
|
||||
public var failOnError: Boolean = false
|
||||
|
||||
public var noStdlib: Boolean = false
|
||||
|
||||
public val additionalArguments: MutableList<Commandline.Argument> = arrayListOf()
|
||||
|
||||
internal var exitCode: Int? = null
|
||||
|
||||
public fun createSrc(): Path {
|
||||
val srcPath = src
|
||||
if (srcPath == null) {
|
||||
@@ -112,16 +83,16 @@ public abstract class KotlinCompilerBaseTask : Task() {
|
||||
final override fun execute() {
|
||||
fillArguments()
|
||||
|
||||
val compilerClass = CompilerClassLoaderHolder.getOrCreateClassLoader().loadClass(compilerFqName)
|
||||
val compilerClass = KotlinAntTaskUtil.getOrCreateClassLoader().loadClass(compilerFqName)
|
||||
val compiler = compilerClass.newInstance()
|
||||
val exec = compilerClass.getMethod("execFullPathsInMessages", javaClass<PrintStream>(), javaClass<Array<String>>())
|
||||
|
||||
log("Compiling ${src!!.list().toList()} => [${output!!.canonicalPath}]");
|
||||
|
||||
val exitCode = exec(compiler, System.err, args.copyToArray())
|
||||
val result = exec(compiler, System.err, args.toTypedArray())
|
||||
exitCode = (result as Enum<*>).ordinal()
|
||||
|
||||
// TODO: support failOnError attribute of javac
|
||||
if ((exitCode as Enum<*>).ordinal() != 0) {
|
||||
if (failOnError && exitCode != 0) {
|
||||
throw BuildException("Compile failed; see the compiler error output for details.")
|
||||
}
|
||||
}
|
||||
|
||||
18
build.xml
18
build.xml
@@ -10,7 +10,7 @@
|
||||
|
||||
<property name="max.heap.size.for.forked.jvm" value="1024m"/>
|
||||
|
||||
<property name="bootstrap.home" value="dependencies/bootstrap-compiler"/>
|
||||
<property name="bootstrap.home" value="${basedir}/dependencies/bootstrap-compiler"/>
|
||||
<property name="bootstrap.compiler.home" value="${bootstrap.home}/Kotlin/kotlinc"/>
|
||||
<property name="bootstrap.runtime" value="${bootstrap.compiler.home}/lib/kotlin-runtime.jar"/>
|
||||
<property name="bootstrap.reflect" value="${bootstrap.compiler.home}/lib/kotlin-reflect.jar"/>
|
||||
@@ -56,6 +56,7 @@
|
||||
|
||||
<path id="classpath">
|
||||
<file file="${bootstrap.runtime}"/>
|
||||
<file file="${bootstrap.reflect}"/>
|
||||
<fileset dir="${idea.sdk}" includes="core/*.jar"/>
|
||||
<pathelement location="${protobuf.jar}"/>
|
||||
|
||||
@@ -517,7 +518,7 @@
|
||||
<available property="jssejar" value="${java.home}/lib/jsse.jar" file="${java.home}/lib/jsse.jar"/>
|
||||
<available property="jssejar" value="${java.home}/../Classes/jsse.jar" file="${java.home}/../Classes/jsse.jar"/>
|
||||
|
||||
<proguard configuration="compiler.pro"/>
|
||||
<proguard configuration="${basedir}/compiler/compiler.pro"/>
|
||||
</else>
|
||||
</if>
|
||||
|
||||
@@ -525,6 +526,7 @@
|
||||
<!-- TODO: don't include both to the jar: it's impossible to test changes to core in the local maven build without bootstrap -->
|
||||
<zipfileset src="${kotlin-home}/lib/kotlin-compiler.jar" includes="**"/>
|
||||
<zipfileset src="${bootstrap.runtime}" includes="**" excludes="META-INF/**"/>
|
||||
<zipfileset src="${bootstrap.reflect}" includes="**" excludes="META-INF/**"/>
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${manifest.impl.vendor}"/>
|
||||
@@ -549,6 +551,7 @@
|
||||
<pathelement path="${idea.sdk}/core/intellij-core.jar"/>
|
||||
<pathelement path="${kotlin-home}/lib/kotlin-compiler.jar"/>
|
||||
<pathelement path="${bootstrap.runtime}"/>
|
||||
<pathelement path="${bootstrap.reflect}"/>
|
||||
</classpath>
|
||||
</kotlinc>
|
||||
|
||||
@@ -573,7 +576,8 @@
|
||||
<compilerarg value="-Xlint:all"/>
|
||||
<classpath>
|
||||
<file file="${bootstrap.runtime}"/>
|
||||
<pathelement location="${dependencies.dir}/ant-1.7/lib/ant.jar"/>
|
||||
<file file="${bootstrap.reflect}"/>
|
||||
<pathelement location="${dependencies.dir}/ant-1.8/lib/ant.jar"/>
|
||||
<pathelement location="${kotlin-home}/lib/kotlin-preloader.jar"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
@@ -823,6 +827,14 @@
|
||||
<fileset dir="${output}/core.src" includes="**/*"/>
|
||||
</jar-content>
|
||||
</pack-runtime-jar>
|
||||
|
||||
<pack-runtime-jar jar-dir="${output}" jar-name="kotlin-reflect-sources-for-maven.jar"
|
||||
implementation-title="${manifest.impl.title.kotlin.jvm.reflect.sources}">
|
||||
<jar-content>
|
||||
<fileset dir="${basedir}/core/reflection.jvm/src" includes="**/*"/>
|
||||
<fileset dir="${output}/core.src" includes="**/*"/>
|
||||
</jar-content>
|
||||
</pack-runtime-jar>
|
||||
</target>
|
||||
|
||||
<target name="runtime"
|
||||
|
||||
@@ -183,7 +183,7 @@ public abstract class AnnotationCodegen {
|
||||
ClassifierDescriptor classifierDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor();
|
||||
assert classifierDescriptor != null : "Annotation descriptor has no class: " + annotationDescriptor;
|
||||
RetentionPolicy rp = getRetentionPolicy(classifierDescriptor);
|
||||
if (rp == RetentionPolicy.SOURCE) {
|
||||
if (rp == RetentionPolicy.SOURCE && typeMapper.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.psi.JetElement;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
@@ -337,8 +336,11 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
|
||||
|
||||
iv.load(0, superClassAsmType);
|
||||
|
||||
if (superClassAsmType.equals(AsmTypes.LAMBDA)) {
|
||||
iv.iconst(funDescriptor.getValueParameters().size());
|
||||
if (superClassAsmType.equals(LAMBDA)) {
|
||||
int arity = funDescriptor.getValueParameters().size();
|
||||
if (funDescriptor.getExtensionReceiverParameter() != null) arity++;
|
||||
if (funDescriptor.getDispatchReceiverParameter() != null) arity++;
|
||||
iv.iconst(arity);
|
||||
iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(I)V", false);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -168,7 +168,8 @@ public class FunctionCodegen {
|
||||
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
|
||||
}
|
||||
|
||||
generateAnnotationsForMethod(functionDescriptor, asmMethod, mv, true);
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType());
|
||||
generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));
|
||||
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
|
||||
generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature);
|
||||
@@ -215,21 +216,10 @@ public class FunctionCodegen {
|
||||
methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
|
||||
}
|
||||
|
||||
private void generateAnnotationsForMethod(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
Method asmMethod,
|
||||
MethodVisitor mv,
|
||||
boolean recordParametersIndices
|
||||
) {
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType());
|
||||
generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor), recordParametersIndices);
|
||||
}
|
||||
|
||||
private void generateParameterAnnotations(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmSignature,
|
||||
boolean recordParametersIndices
|
||||
@NotNull JvmMethodSignature jvmSignature
|
||||
) {
|
||||
Iterator<ValueParameterDescriptor> iterator = functionDescriptor.getValueParameters().iterator();
|
||||
List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
|
||||
@@ -244,9 +234,7 @@ public class FunctionCodegen {
|
||||
|
||||
if (kind == JvmMethodParameterKind.VALUE) {
|
||||
ValueParameterDescriptor parameter = iterator.next();
|
||||
if (recordParametersIndices) {
|
||||
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
|
||||
}
|
||||
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
|
||||
AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType());
|
||||
}
|
||||
}
|
||||
@@ -613,7 +601,9 @@ public class FunctionCodegen {
|
||||
getThrownExceptions(functionDescriptor, typeMapper)
|
||||
);
|
||||
|
||||
generateAnnotationsForMethod(functionDescriptor, defaultMethod, mv, false);
|
||||
// Only method annotations are copied to the $default method. Parameter annotations are not copied until there are valid use cases;
|
||||
// enum constructors have two additional synthetic parameters which somewhat complicate this task
|
||||
AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType());
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
if (this.owner instanceof PackageFacadeContext) {
|
||||
|
||||
@@ -81,6 +81,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCall;
|
||||
@@ -225,6 +226,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
|
||||
|
||||
generateReflectionObjectFieldIfNeeded();
|
||||
|
||||
generateEnumEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -360,7 +363,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateSyntheticAccessors();
|
||||
|
||||
generateEnumMethodsAndConstInitializers();
|
||||
generateEnumMethods();
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
@@ -764,11 +767,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
private void generateEnumMethodsAndConstInitializers() {
|
||||
private void generateEnumMethods() {
|
||||
if (isEnumClass(descriptor)) {
|
||||
generateEnumValuesMethod();
|
||||
generateEnumValueOfMethod();
|
||||
initializeEnumConstants();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1065,6 +1067,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateSecondaryConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
||||
if (!canHaveDeclaredConstructors(descriptor)) return;
|
||||
|
||||
ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||
|
||||
functionCodegen.generateMethod(OtherOrigin(descriptorToDeclaration(constructorDescriptor), constructorDescriptor),
|
||||
@@ -1615,24 +1619,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration(JetDeclaration declaration) {
|
||||
if (declaration instanceof JetEnumEntry) {
|
||||
String name = declaration.getName();
|
||||
assert name != null : "Enum entry has no name: " + declaration.getText();
|
||||
ClassDescriptor entryDescriptor = bindingContext.get(BindingContext.CLASS, declaration);
|
||||
FieldVisitor fv = v.newField(OtherOrigin(declaration, entryDescriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL,
|
||||
name, classAsmType.getDescriptor(), null, null);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(entryDescriptor, null);
|
||||
myEnumConstants.add((JetEnumEntry) declaration);
|
||||
private void generateEnumEntries() {
|
||||
if (descriptor.getKind() != ClassKind.ENUM_CLASS) return;
|
||||
|
||||
List<JetEnumEntry> enumEntries = KotlinPackage.filterIsInstance(element.getDeclarations(), JetEnumEntry.class);
|
||||
|
||||
for (JetEnumEntry enumEntry : enumEntries) {
|
||||
ClassDescriptor descriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
|
||||
FieldVisitor fv = v.newField(OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL,
|
||||
descriptor.getName().asString(), classAsmType.getDescriptor(), null, null);
|
||||
AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor, null);
|
||||
}
|
||||
|
||||
super.generateDeclaration(declaration);
|
||||
initializeEnumConstants(enumEntries);
|
||||
}
|
||||
|
||||
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
|
||||
|
||||
private void initializeEnumConstants() {
|
||||
private void initializeEnumConstants(@NotNull List<JetEnumEntry> enumEntries) {
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
@@ -1642,48 +1644,39 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
v.newField(OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME,
|
||||
arrayAsmType.getDescriptor(), null, null);
|
||||
|
||||
iv.iconst(myEnumConstants.size());
|
||||
iv.iconst(enumEntries.size());
|
||||
iv.newarray(classAsmType);
|
||||
|
||||
if (!myEnumConstants.isEmpty()) {
|
||||
if (!enumEntries.isEmpty()) {
|
||||
iv.dup();
|
||||
for (int ordinal = 0, size = myEnumConstants.size(); ordinal < size; ordinal++) {
|
||||
initializeEnumConstant(codegen, ordinal);
|
||||
for (int ordinal = 0, size = enumEntries.size(); ordinal < size; ordinal++) {
|
||||
initializeEnumConstant(enumEntries, ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
iv.putstatic(classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, arrayAsmType.getDescriptor());
|
||||
}
|
||||
|
||||
private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) {
|
||||
private void initializeEnumConstant(@NotNull List<JetEnumEntry> enumEntries, int ordinal) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
InstructionAdapter iv = codegen.v;
|
||||
JetEnumEntry enumConstant = myEnumConstants.get(ordinal);
|
||||
JetEnumEntry enumEntry = enumEntries.get(ordinal);
|
||||
|
||||
iv.dup();
|
||||
iv.iconst(ordinal);
|
||||
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant);
|
||||
assert classDescriptor != null;
|
||||
ClassDescriptor classDescriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
|
||||
Type implClass = typeMapper.mapClass(classDescriptor);
|
||||
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
|
||||
if (delegationSpecifiers.size() > 1) {
|
||||
throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
|
||||
}
|
||||
|
||||
iv.anew(implClass);
|
||||
iv.dup();
|
||||
|
||||
iv.aconst(enumConstant.getName());
|
||||
iv.aconst(enumEntry.getName());
|
||||
iv.iconst(ordinal);
|
||||
|
||||
if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumConstant)) {
|
||||
JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
|
||||
if (!(specifier instanceof JetDelegatorToSuperCall)) {
|
||||
throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
|
||||
}
|
||||
|
||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(specifier, bindingContext);
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers();
|
||||
if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
|
||||
|
||||
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor());
|
||||
|
||||
@@ -1694,7 +1687,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
iv.dup();
|
||||
iv.putstatic(classAsmType.getInternalName(), enumConstant.getName(), classAsmType.getDescriptor());
|
||||
iv.putstatic(classAsmType.getInternalName(), enumEntry.getName(), classAsmType.getDescriptor());
|
||||
iv.astore(OBJECT_TYPE);
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ public class PropertyCodegen {
|
||||
public void generateConstructorPropertyAsMethodForAnnotationClass(JetParameter p, PropertyDescriptor descriptor) {
|
||||
JvmMethodSignature signature = typeMapper.mapAnnotationParameterSignature(descriptor);
|
||||
String name = p.getName();
|
||||
assert name != null : "Annotation parameter has no name: " + p.getText();
|
||||
if (name == null) return;
|
||||
MethodVisitor mv = v.newMethod(
|
||||
OtherOrigin(p, descriptor), ACC_PUBLIC | ACC_ABSTRACT, name,
|
||||
signature.getAsmMethod().getDescriptor(),
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnStream
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.org.objectweb.asm.tree.LineNumberNode
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import kotlin.properties.Delegates
|
||||
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.codegen.SourceInfo
|
||||
class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) {
|
||||
|
||||
val lineNumbers =
|
||||
InsnStream(node.instructions.getFirst(), null).stream().filterIsInstance<LineNumberNode>().map {
|
||||
InsnSequence(node.instructions.getFirst(), null).stream().filterIsInstance<LineNumberNode>().map {
|
||||
val index = Collections.binarySearch(classSMAP.intervals, RangeMapping(it.line, it.line, 1)) {
|
||||
value, key ->
|
||||
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
|
||||
@@ -28,7 +28,7 @@ val AbstractInsnNode.isMeaningful : Boolean get() =
|
||||
else -> true
|
||||
}
|
||||
|
||||
class InsnStream(val from: AbstractInsnNode, val to: AbstractInsnNode?) : Stream<AbstractInsnNode> {
|
||||
class InsnSequence(val from: AbstractInsnNode, val to: AbstractInsnNode?) : Sequence<AbstractInsnNode> {
|
||||
override fun iterator(): Iterator<AbstractInsnNode> {
|
||||
return object : Iterator<AbstractInsnNode> {
|
||||
var current: AbstractInsnNode? = from
|
||||
@@ -44,14 +44,14 @@ class InsnStream(val from: AbstractInsnNode, val to: AbstractInsnNode?) : Stream
|
||||
|
||||
fun MethodNode.prepareForEmitting() {
|
||||
tryCatchBlocks = tryCatchBlocks.filter { tcb ->
|
||||
InsnStream(tcb.start, tcb.end).any { insn ->
|
||||
InsnSequence(tcb.start, tcb.end).any { insn ->
|
||||
insn.isMeaningful
|
||||
}
|
||||
}
|
||||
|
||||
// local variables with live ranges starting after last meaningful instruction lead to VerifyError
|
||||
localVariables = localVariables.filter { lv ->
|
||||
InsnStream(lv.start, instructions.getLast()).any { insn ->
|
||||
InsnSequence(lv.start, lv.end).any { insn ->
|
||||
insn.isMeaningful
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,10 +77,10 @@ import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationCons
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class JetTypeMapper {
|
||||
private static final String DEFAULT_CONSTRUCTOR_MARKER_INTERNAL_CLASS_NAME = "kotlin/jvm/internal/DefaultConstructorMarker";
|
||||
private final BindingContext bindingContext;
|
||||
private final ClassBuilderMode classBuilderMode;
|
||||
|
||||
@@ -780,7 +780,7 @@ public class JetTypeMapper {
|
||||
int maskArgumentsCount = (argumentsCount + Integer.SIZE - 1) / Integer.SIZE;
|
||||
String additionalArgs = StringUtil.repeat(Type.INT_TYPE.getDescriptor(), maskArgumentsCount);
|
||||
if (isConstructor(method)) {
|
||||
additionalArgs += Type.getObjectType(DEFAULT_CONSTRUCTOR_MARKER_INTERNAL_CLASS_NAME).getDescriptor();
|
||||
additionalArgs += DEFAULT_CONSTRUCTOR_MARKER.getDescriptor();
|
||||
}
|
||||
String result = descriptor.replace(")", additionalArgs + ")");
|
||||
if (dispatchReceiverDescriptor != null && !isConstructor(method)) {
|
||||
@@ -789,6 +789,10 @@ public class JetTypeMapper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public ClassBuilderMode getClassBuilderMode() {
|
||||
return classBuilderMode;
|
||||
}
|
||||
|
||||
private static boolean isConstructor(@NotNull Method method) {
|
||||
return "<init>".equals(method.getName());
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class SwitchCodegenUtil {
|
||||
// ensure that expression is constant
|
||||
JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression();
|
||||
|
||||
assert patternExpression != null : "expression in when should not be null";
|
||||
if (patternExpression == null) return false;
|
||||
|
||||
CompileTimeConstant constant = ExpressionCodegen.getCompileTimeConstant(patternExpression, bindingContext);
|
||||
if (constant == null || !predicate.invoke(constant)) {
|
||||
|
||||
@@ -78,6 +78,7 @@ import org.jetbrains.kotlin.parsing.JetScriptDefinitionProvider
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer
|
||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.CliDeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
@@ -141,6 +142,7 @@ public class KotlinCoreEnvironment private(
|
||||
ExternalDeclarationsProvider.registerExtensionPoint(project)
|
||||
ExpressionCodegenExtension.registerExtensionPoint(project)
|
||||
ClassBuilderInterceptorExtension.registerExtensionPoint(project)
|
||||
AnalysisCompletedHandlerExtension.registerExtensionPoint(project)
|
||||
|
||||
for (registrar in configuration.getList(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)) {
|
||||
registrar.registerProjectComponents(project, configuration)
|
||||
|
||||
@@ -299,6 +299,8 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!result.getShouldGenerateCode()) return null;
|
||||
|
||||
result.throwIfError();
|
||||
|
||||
return generate(environment, result, environment.getSourceFiles(), null, null);
|
||||
|
||||
@@ -91,7 +91,9 @@ messages/**)
|
||||
|
||||
# for gradle plugin and other server tools
|
||||
-keep class com.intellij.openapi.util.io.ZipFileCache { public *; }
|
||||
-keep class com.intellij.openapi.util.LowMemoryWatcher { public *; }
|
||||
|
||||
# for j2k
|
||||
-keep class com.intellij.codeInsight.NullableNotNullManager { public protected *; }
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
@@ -109,7 +109,14 @@ public class JavaClassImpl extends JavaClassifierImpl<PsiClass> implements JavaC
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<JavaField> getFields() {
|
||||
return fields(getPsi().getFields());
|
||||
// ex. Android plugin generates LightFields for resources started from '.' (.DS_Store file etc)
|
||||
return fields(KotlinPackage.filter(getPsi().getFields(), new Function1<PsiField, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(PsiField field) {
|
||||
String name = field.getName();
|
||||
return name != null && Name.isValidIdentifier(name);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -183,7 +183,7 @@ public class JavaElementCollectionFromPsiArrayUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<JavaField> fields(@NotNull PsiField[] fields) {
|
||||
public static Collection<JavaField> fields(@NotNull Iterable<PsiField> fields) {
|
||||
return convert(fields, Factories.FIELDS);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ public class AsmTypes {
|
||||
public static final String REF_TYPE_PREFIX = "kotlin/jvm/internal/Ref$";
|
||||
public static final Type OBJECT_REF_TYPE = Type.getObjectType(REF_TYPE_PREFIX + "ObjectRef");
|
||||
|
||||
public static final Type DEFAULT_CONSTRUCTOR_MARKER = Type.getObjectType("kotlin/jvm/internal/DefaultConstructorMarker");
|
||||
|
||||
@NotNull
|
||||
private static Type reflect(@NotNull String className) {
|
||||
return Type.getObjectType("kotlin/reflect/" + className);
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.context.ModuleContext;
|
||||
import org.jetbrains.kotlin.context.MutableModuleContext;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ModuleParameters;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
|
||||
import org.jetbrains.kotlin.di.InjectorForTopDownAnalyzerForJvm;
|
||||
@@ -36,10 +37,8 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
|
||||
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.ImportPath;
|
||||
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension;
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -148,7 +147,19 @@ public enum TopDownAnalyzerFacadeForJVM {
|
||||
additionalProviders.add(injector.getJavaDescriptorResolver().getPackageFragmentProvider());
|
||||
|
||||
injector.getLazyTopDownAnalyzerForTopLevel().analyzeFiles(topDownAnalysisMode, allFiles, additionalProviders);
|
||||
return AnalysisResult.success(trace.getBindingContext(), moduleContext.getModule());
|
||||
|
||||
BindingContext bindingContext = trace.getBindingContext();
|
||||
ModuleDescriptor module = moduleContext.getModule();
|
||||
|
||||
Collection<AnalysisCompletedHandlerExtension> analysisCompletedHandlerExtensions =
|
||||
AnalysisCompletedHandlerExtension.Companion.getInstances(moduleContext.getProject());
|
||||
|
||||
for (AnalysisCompletedHandlerExtension extension : analysisCompletedHandlerExtensions) {
|
||||
AnalysisResult result = extension.analysisCompleted(project, module, bindingContext, files);
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
return AnalysisResult.success(bindingContext, module);
|
||||
}
|
||||
finally {
|
||||
injector.destroy();
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.jvm.extensions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
public interface AnalysisCompletedHandlerExtension {
|
||||
companion object : ProjectExtensionDescriptor<AnalysisCompletedHandlerExtension>(
|
||||
"org.jetbrains.kotlin.analyzeCompleteHandlerExtension",
|
||||
javaClass<AnalysisCompletedHandlerExtension>()
|
||||
)
|
||||
|
||||
public fun analysisCompleted(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
bindingContext: BindingContext,
|
||||
files: Collection<JetFile>): AnalysisResult?
|
||||
}
|
||||
@@ -21,9 +21,10 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
public data open class AnalysisResult protected (
|
||||
public data open class AnalysisResult protected constructor(
|
||||
public val bindingContext: BindingContext,
|
||||
public val moduleDescriptor: ModuleDescriptor
|
||||
public val moduleDescriptor: ModuleDescriptor,
|
||||
public val shouldGenerateCode: Boolean = true
|
||||
) {
|
||||
|
||||
public val error: Throwable
|
||||
@@ -43,7 +44,11 @@ public data open class AnalysisResult protected (
|
||||
public val EMPTY: AnalysisResult = success(BindingContext.EMPTY, ErrorUtils.getErrorModule())
|
||||
|
||||
platformStatic public fun success(bindingContext: BindingContext, module: ModuleDescriptor): AnalysisResult {
|
||||
return AnalysisResult(bindingContext, module)
|
||||
return AnalysisResult(bindingContext, module, true)
|
||||
}
|
||||
|
||||
platformStatic public fun success(bindingContext: BindingContext, module: ModuleDescriptor, shouldGenerateCode: Boolean): AnalysisResult {
|
||||
return AnalysisResult(bindingContext, module, shouldGenerateCode)
|
||||
}
|
||||
|
||||
platformStatic public fun error(bindingContext: BindingContext, error: Throwable): AnalysisResult {
|
||||
|
||||
@@ -674,7 +674,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
else if (owner instanceof JetPrimaryConstructor) {
|
||||
if (!((JetParameter) element).hasValOrVarNode() &&
|
||||
!((JetPrimaryConstructor) owner).getContainingClass().isAnnotation()) {
|
||||
!((JetPrimaryConstructor) owner).getContainingClassOrObject().isAnnotation()) {
|
||||
report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor), ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,9 +149,12 @@ public final class WhenChecker {
|
||||
for (JetWhenEntry entry : expression.getEntries()) {
|
||||
for (JetWhenCondition condition : entry.getConditions()) {
|
||||
if (condition instanceof JetWhenConditionWithExpression) {
|
||||
JetType type = trace.getBindingContext().getType(((JetWhenConditionWithExpression) condition).getExpression());
|
||||
if (type != null && KotlinBuiltIns.isNothingOrNullableNothing(type)) {
|
||||
return true;
|
||||
JetWhenConditionWithExpression conditionWithExpression = (JetWhenConditionWithExpression) condition;
|
||||
if (conditionWithExpression.getExpression() != null) {
|
||||
JetType type = trace.getBindingContext().getType(conditionWithExpression.getExpression());
|
||||
if (type != null && KotlinBuiltIns.isNothingOrNullableNothing(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.cfg.pseudocode
|
||||
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import com.intellij.util.SmartFMap
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||
|
||||
public trait TypePredicate: (JetType) -> Boolean {
|
||||
[suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
|
||||
override fun invoke(typeToCheck: JetType): Boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ public fun JetElement.getContainingPseudocode(context: BindingContext): Pseudoco
|
||||
?: return null
|
||||
|
||||
val enclosingPseudocodeDeclaration = (pseudocodeDeclaration as? JetFunctionLiteral)?.let {
|
||||
it.parents(withItself = false).firstOrNull { it is JetDeclaration && it !is JetFunctionLiteral } as? JetDeclaration
|
||||
it.parents.firstOrNull { it is JetDeclaration && it !is JetFunctionLiteral } as? JetDeclaration
|
||||
} ?: pseudocodeDeclaration
|
||||
|
||||
val enclosingPseudocode = PseudocodeUtil.generatePseudocode(enclosingPseudocodeDeclaration, context)
|
||||
|
||||
@@ -165,7 +165,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<JetConstructorDelegationReferenceExpression> CYCLIC_CONSTRUCTOR_DELEGATION_CALL = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetSecondaryConstructor> SECONDARY_CONSTRUCTOR_IN_OBJECT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetDeclaration> CONSTRUCTOR_IN_OBJECT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
DiagnosticFactory0<JetDelegatorToSuperCall> SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<JetConstructorDelegationCall> PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED =
|
||||
@@ -188,7 +188,7 @@ public interface Errors {
|
||||
.create(WARNING, modifierSetPosition(JetTokens.OPEN_KEYWORD));
|
||||
DiagnosticFactory0<JetModifierListOwner> TRAIT_CAN_NOT_BE_FINAL = DiagnosticFactory0.create(ERROR, FINAL_MODIFIER);
|
||||
|
||||
DiagnosticFactory0<PsiElement> CONSTRUCTOR_IN_TRAIT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<JetDeclaration> CONSTRUCTOR_IN_TRAIT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
DiagnosticFactory0<PsiElement> SUPERTYPE_INITIALIZED_IN_TRAIT = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@@ -397,7 +397,12 @@ public interface Errors {
|
||||
DiagnosticFactory0<JetReferenceExpression> ARGUMENT_PASSED_TWICE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<JetReferenceExpression, JetReferenceExpression> NAMED_PARAMETER_NOT_FOUND =
|
||||
DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE);
|
||||
DiagnosticFactory0<PsiElement> NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, BadNamedArgumentsTarget> NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
enum BadNamedArgumentsTarget {
|
||||
NON_KOTLIN_FUNCTION,
|
||||
INVOKE_ON_FUNCTION_TYPE
|
||||
}
|
||||
|
||||
DiagnosticFactory0<JetExpression> VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<LeafPsiElement> NON_VARARG_SPREAD = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@@ -156,6 +156,11 @@ public object PositioningStrategies {
|
||||
is JetObjectDeclaration -> {
|
||||
return DECLARATION_NAME.mark(element)
|
||||
}
|
||||
is JetPrimaryConstructor -> {
|
||||
val begin = element.getConstructorKeyword() ?: element.getValueParameterList() ?: return markElement(element)
|
||||
val end = element.getValueParameterList() ?: element.getConstructorKeyword()
|
||||
return markRange(begin, end)
|
||||
}
|
||||
is JetSecondaryConstructor -> {
|
||||
return markRange(element.getConstructorKeyword(), element.getValueParameterList() ?: element.getConstructorKeyword())
|
||||
}
|
||||
|
||||
@@ -155,7 +155,21 @@ public class DefaultErrorMessages {
|
||||
MAP.put(MIXING_NAMED_AND_POSITIONED_ARGUMENTS, "Mixing named and positioned arguments is not allowed");
|
||||
MAP.put(ARGUMENT_PASSED_TWICE, "An argument is already passed for this parameter");
|
||||
MAP.put(NAMED_PARAMETER_NOT_FOUND, "Cannot find a parameter with this name: {0}", ELEMENT_TEXT);
|
||||
MAP.put(NAMED_ARGUMENTS_NOT_ALLOWED, "Named arguments are not allowed for non-Kotlin functions");
|
||||
MAP.put(NAMED_ARGUMENTS_NOT_ALLOWED, "Named arguments are not allowed for {0}", new Renderer<BadNamedArgumentsTarget>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull BadNamedArgumentsTarget target) {
|
||||
switch (target) {
|
||||
case NON_KOTLIN_FUNCTION:
|
||||
return "non-Kotlin functions";
|
||||
case INVOKE_ON_FUNCTION_TYPE:
|
||||
return "function types";
|
||||
default:
|
||||
throw new AssertionError(target);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
MAP.put(VARARG_OUTSIDE_PARENTHESES, "Passing value as a vararg is only allowed inside a parenthesized argument list");
|
||||
MAP.put(NON_VARARG_SPREAD, "The spread operator (*foo) may only be applied in a vararg position");
|
||||
|
||||
@@ -402,7 +416,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(SINGLETON_IN_SUPERTYPE, "Cannot inherit from a singleton");
|
||||
|
||||
MAP.put(CYCLIC_CONSTRUCTOR_DELEGATION_CALL, "There's a cycle in the delegation calls chain");
|
||||
MAP.put(SECONDARY_CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects");
|
||||
MAP.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects");
|
||||
MAP.put(SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR, "Supertype initialization is impossible without primary constructor");
|
||||
MAP.put(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED, "Primary constructor call expected");
|
||||
MAP.put(DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR, "Call to super is not allowed in enum constructor");
|
||||
|
||||
@@ -86,3 +86,9 @@ object TrailingCommentsBinder : WhitespacesAndCommentsBinder {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
object DoNotBindAnything : WhitespacesAndCommentsBinder {
|
||||
override fun getEdgePosition(tokens: List<IElementType>, atStreamEdge: Boolean, getter: WhitespacesAndCommentsBinder.TokenTextGetter): Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -215,8 +215,8 @@ public class JetParsing extends AbstractJetParsing {
|
||||
parseFileAnnotationList(FILE_ANNOTATIONS_WHEN_PACKAGE_OMITTED);
|
||||
packageDirective = mark();
|
||||
packageDirective.done(PACKAGE_DIRECTIVE);
|
||||
// this is necessary to allow comments at the start of the file to be bound to the first declaration:
|
||||
packageDirective.setCustomEdgeTokenBinders(PrecedingCommentsBinder.INSTANCE$, null);
|
||||
// this is necessary to allow comments at the start of the file to be bound to the first declaration
|
||||
packageDirective.setCustomEdgeTokenBinders(DoNotBindAnything.INSTANCE$, null);
|
||||
}
|
||||
|
||||
parseImportDirectives();
|
||||
@@ -351,13 +351,15 @@ public class JetParsing extends AbstractJetParsing {
|
||||
}
|
||||
|
||||
private void parseImportDirectives() {
|
||||
if (at(IMPORT_KEYWORD)) {
|
||||
PsiBuilder.Marker importList = mark();
|
||||
while (at(IMPORT_KEYWORD)) {
|
||||
parseImportDirective();
|
||||
}
|
||||
importList.done(IMPORT_LIST);
|
||||
PsiBuilder.Marker importList = mark();
|
||||
if (!at(IMPORT_KEYWORD)) {
|
||||
// this is necessary to allow comments at the start of the file to be bound to the first declaration
|
||||
importList.setCustomEdgeTokenBinders(DoNotBindAnything.INSTANCE$, null);
|
||||
}
|
||||
while (at(IMPORT_KEYWORD)) {
|
||||
parseImportDirective();
|
||||
}
|
||||
importList.done(IMPORT_LIST);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -705,14 +707,18 @@ public class JetParsing extends AbstractJetParsing {
|
||||
* class
|
||||
* : modifiers ("class" | "interface") SimpleName
|
||||
* typeParameters?
|
||||
* modifiers ("(" primaryConstructorParameter{","} ")")?
|
||||
* primaryConstructor?
|
||||
* (":" annotations delegationSpecifier{","})?
|
||||
* typeConstraints
|
||||
* (classBody? | enumClassBody)
|
||||
* ;
|
||||
*
|
||||
* primaryConstructor
|
||||
* : (modifiers "constructor")? ("(" functionParameter{","} ")")
|
||||
* ;
|
||||
*
|
||||
* object
|
||||
* : "object" SimpleName? ":" delegationSpecifier{","}? classBody?
|
||||
* : "object" SimpleName? primaryConstructor? ":" delegationSpecifier{","}? classBody?
|
||||
* ;
|
||||
*/
|
||||
IElementType parseClassOrObject(
|
||||
@@ -754,7 +760,6 @@ public class JetParsing extends AbstractJetParsing {
|
||||
boolean typeParametersDeclared = parseTypeParameterList(TYPE_PARAMETER_GT_RECOVERY_SET);
|
||||
typeParamsMarker.error("Type parameters are not allowed for objects");
|
||||
|
||||
OptionalMarker constructorModifiersMarker = new OptionalMarker(object);
|
||||
PsiBuilder.Marker beforeConstructorModifiers = mark();
|
||||
PsiBuilder.Marker primaryConstructorMarker = mark();
|
||||
boolean hasConstructorModifiers = parseModifierList(
|
||||
@@ -762,9 +767,8 @@ public class JetParsing extends AbstractJetParsing {
|
||||
);
|
||||
|
||||
// Some modifiers found, but no parentheses following: class has already ended, and we are looking at something else
|
||||
if ((object && at(CONSTRUCTOR_KEYWORD)) || (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD))) {
|
||||
if (hasConstructorModifiers && !atSet(LPAR, LBRACE, COLON, CONSTRUCTOR_KEYWORD)) {
|
||||
beforeConstructorModifiers.rollbackTo();
|
||||
constructorModifiersMarker.drop();
|
||||
return object ? OBJECT_DECLARATION : CLASS;
|
||||
}
|
||||
|
||||
@@ -796,7 +800,6 @@ public class JetParsing extends AbstractJetParsing {
|
||||
else {
|
||||
primaryConstructorMarker.drop();
|
||||
}
|
||||
constructorModifiersMarker.error("Constructors are not allowed for objects");
|
||||
|
||||
if (at(COLON)) {
|
||||
advance(); // COLON
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.JetNodeTypes;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinClassStub;
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JetClass extends JetTypeParameterListOwnerStub<KotlinClassStub> implements JetClassOrObject {
|
||||
|
||||
public JetClass(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public JetClass(@NotNull KotlinClassStub stub) {
|
||||
super(stub, JetStubElementTypes.CLASS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetDeclaration> getDeclarations() {
|
||||
JetClassBody body = getBody();
|
||||
if (body == null) return Collections.emptyList();
|
||||
|
||||
return body.getDeclarations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitClass(this, data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetPrimaryConstructor getPrimaryConstructor() {
|
||||
return getStubOrPsiChild(JetStubElementTypes.PRIMARY_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetParameterList getPrimaryConstructorParameterList() {
|
||||
JetPrimaryConstructor primaryConstructor = getPrimaryConstructor();
|
||||
return primaryConstructor != null ? primaryConstructor.getValueParameterList() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetParameter> getPrimaryConstructorParameters() {
|
||||
JetParameterList list = getPrimaryConstructorParameterList();
|
||||
if (list == null) return Collections.emptyList();
|
||||
return list.getParameters();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetPrimaryConstructor createPrimaryConstructorIfAbsent() {
|
||||
JetPrimaryConstructor constructor = getPrimaryConstructor();
|
||||
if (constructor != null) return constructor;
|
||||
PsiElement anchor = getTypeParameterList();
|
||||
if (anchor == null) anchor = getNameIdentifier();
|
||||
if (anchor == null) anchor = getLastChild();
|
||||
return (JetPrimaryConstructor) addAfter(new JetPsiFactory(getProject()).createPrimaryConstructor(), anchor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetParameterList createPrimaryConstructorParameterListIfAbsent() {
|
||||
JetPrimaryConstructor constructor = createPrimaryConstructorIfAbsent();
|
||||
JetParameterList parameterList = constructor.getValueParameterList();
|
||||
if (parameterList != null) return parameterList;
|
||||
return (JetParameterList) constructor.add(new JetPsiFactory(getProject()).createParameterList("()"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JetDelegationSpecifierList getDelegationSpecifierList() {
|
||||
return getStubOrPsiChild(JetStubElementTypes.DELEGATION_SPECIFIER_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetDelegationSpecifier> getDelegationSpecifiers() {
|
||||
JetDelegationSpecifierList list = getDelegationSpecifierList();
|
||||
return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetModifierList getPrimaryConstructorModifierList() {
|
||||
JetPrimaryConstructor primaryConstructor = getPrimaryConstructor();
|
||||
return primaryConstructor != null ? primaryConstructor.getModifierList() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetClassInitializer> getAnonymousInitializers() {
|
||||
JetClassBody body = getBody();
|
||||
if (body == null) return Collections.emptyList();
|
||||
|
||||
return body.getAnonymousInitializers();
|
||||
}
|
||||
|
||||
public boolean hasExplicitPrimaryConstructor() {
|
||||
return getPrimaryConstructor() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetObjectDeclarationName getNameAsDeclaration() {
|
||||
return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetClassBody getBody() {
|
||||
return getStubOrPsiChild(JetStubElementTypes.CLASS_BODY);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getColon() {
|
||||
return findChildByType(JetTokens.COLON);
|
||||
}
|
||||
|
||||
public List<JetProperty> getProperties() {
|
||||
JetClassBody body = getBody();
|
||||
if (body == null) return Collections.emptyList();
|
||||
|
||||
return body.getProperties();
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
KotlinClassStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.isInterface();
|
||||
}
|
||||
|
||||
return findChildByType(JetTokens.TRAIT_KEYWORD) != null ||
|
||||
findChildByType(JetTokens.INTERFACE_KEYWORD) != null;
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return hasModifier(JetTokens.ENUM_KEYWORD);
|
||||
}
|
||||
|
||||
public boolean isAnnotation() {
|
||||
return hasModifier(JetTokens.ANNOTATION_KEYWORD);
|
||||
}
|
||||
|
||||
public boolean isInner() {
|
||||
return hasModifier(JetTokens.INNER_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
if (super.isEquivalentTo(another)) {
|
||||
return true;
|
||||
}
|
||||
if (another instanceof JetClass) {
|
||||
String fq1 = getQualifiedName();
|
||||
String fq2 = ((JetClass) another).getQualifiedName();
|
||||
return fq1 != null && fq2 != null && fq1.equals(fq2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getQualifiedName() {
|
||||
KotlinClassStub stub = getStub();
|
||||
if (stub != null) {
|
||||
FqName fqName = stub.getFqName();
|
||||
return fqName == null ? null : fqName.asString();
|
||||
}
|
||||
|
||||
List<String> parts = new ArrayList<String>();
|
||||
JetClassOrObject current = this;
|
||||
while (current != null) {
|
||||
parts.add(current.getName());
|
||||
current = PsiTreeUtil.getParentOfType(current, JetClassOrObject.class);
|
||||
}
|
||||
PsiFile file = getContainingFile();
|
||||
if (!(file instanceof JetFile)) return null;
|
||||
String fileQualifiedName = ((JetFile) file).getPackageFqName().asString();
|
||||
if (!fileQualifiedName.isEmpty()) {
|
||||
parts.add(fileQualifiedName);
|
||||
}
|
||||
Collections.reverse(parts);
|
||||
return StringUtil.join(parts, ".");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return ItemPresentationProviders.getItemPresentation(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopLevel() {
|
||||
return getContainingFile() == getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
KotlinClassStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.isLocal();
|
||||
}
|
||||
return JetPsiUtil.isLocal(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetObjectDeclaration> getCompanionObjects() {
|
||||
JetClassBody body = getBody();
|
||||
if (body == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return body.getAllCompanionObjects();
|
||||
}
|
||||
|
||||
public boolean hasPrimaryConstructor() {
|
||||
return hasExplicitPrimaryConstructor() || !hasSecondaryConstructors();
|
||||
}
|
||||
|
||||
private boolean hasSecondaryConstructors() {
|
||||
return !getSecondaryConstructors().isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetSecondaryConstructor> getSecondaryConstructors() {
|
||||
JetClassBody body = getBody();
|
||||
return body != null ? body.getSecondaryConstructors() : Collections.<JetSecondaryConstructor>emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getClassOrInterfaceKeyword() {
|
||||
return findChildByType(TokenSet.create(JetTokens.CLASS_KEYWORD, JetTokens.INTERFACE_KEYWORD));
|
||||
}
|
||||
}
|
||||
107
compiler/frontend/src/org/jetbrains/kotlin/psi/JetClass.kt
Normal file
107
compiler/frontend/src/org/jetbrains/kotlin/psi/JetClass.kt
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.navigation.ItemPresentation
|
||||
import com.intellij.navigation.ItemPresentationProviders
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinClassStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
|
||||
public open class JetClass : JetClassOrObject {
|
||||
public constructor(node: ASTNode) : super(node)
|
||||
public constructor(stub: KotlinClassStub) : super(stub, JetStubElementTypes.CLASS)
|
||||
|
||||
override fun getStub(): KotlinClassStub? = super.getStub() as? KotlinClassStub
|
||||
|
||||
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D): R {
|
||||
return visitor.visitClass(this, data)
|
||||
}
|
||||
|
||||
public fun createPrimaryConstructorIfAbsent(): JetPrimaryConstructor {
|
||||
val constructor = getPrimaryConstructor()
|
||||
if (constructor != null) return constructor
|
||||
var anchor: PsiElement? = getTypeParameterList()
|
||||
if (anchor == null) anchor = getNameIdentifier()
|
||||
if (anchor == null) anchor = getLastChild()
|
||||
return addAfter(JetPsiFactory(getProject()).createPrimaryConstructor(), anchor) as JetPrimaryConstructor
|
||||
}
|
||||
|
||||
public fun createPrimaryConstructorParameterListIfAbsent(): JetParameterList {
|
||||
val constructor = createPrimaryConstructorIfAbsent()
|
||||
val parameterList = constructor.getValueParameterList()
|
||||
if (parameterList != null) return parameterList
|
||||
return constructor.add(JetPsiFactory(getProject()).createParameterList("()")) as JetParameterList
|
||||
}
|
||||
|
||||
public fun getColon(): PsiElement? = findChildByType(JetTokens.COLON)
|
||||
|
||||
public fun getProperties(): List<JetProperty> = getBody()?.getProperties().orEmpty()
|
||||
|
||||
public fun isInterface(): Boolean =
|
||||
getStub()?.isInterface()
|
||||
?: (findChildByType<PsiElement>(JetTokens.TRAIT_KEYWORD) != null || findChildByType<PsiElement>(JetTokens.INTERFACE_KEYWORD) != null)
|
||||
|
||||
public fun isEnum(): Boolean = hasModifier(JetTokens.ENUM_KEYWORD)
|
||||
public fun isInner(): Boolean = hasModifier(JetTokens.INNER_KEYWORD)
|
||||
|
||||
override fun isEquivalentTo(another: PsiElement?): Boolean {
|
||||
if (super.isEquivalentTo(another)) {
|
||||
return true
|
||||
}
|
||||
if (another is JetClass) {
|
||||
val fq1 = getQualifiedName()
|
||||
val fq2 = another.getQualifiedName()
|
||||
return fq1 != null && fq2 != null && fq1 == fq2
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getQualifiedName(): String? {
|
||||
val stub = getStub()
|
||||
if (stub != null) {
|
||||
val fqName = stub.getFqName()
|
||||
return fqName?.asString()
|
||||
}
|
||||
|
||||
val parts = ArrayList<String>()
|
||||
var current: JetClassOrObject? = this
|
||||
while (current != null) {
|
||||
parts.add(current.getName())
|
||||
current = PsiTreeUtil.getParentOfType<JetClassOrObject>(current, javaClass<JetClassOrObject>())
|
||||
}
|
||||
val file = getContainingFile()
|
||||
if (file !is JetFile) return null
|
||||
val fileQualifiedName = file.getPackageFqName().asString()
|
||||
if (!fileQualifiedName.isEmpty()) {
|
||||
parts.add(fileQualifiedName)
|
||||
}
|
||||
Collections.reverse(parts)
|
||||
return StringUtil.join(parts, ".")
|
||||
}
|
||||
|
||||
public fun getCompanionObjects(): List<JetObjectDeclaration> = getBody()?.getAllCompanionObjects().orEmpty()
|
||||
|
||||
public fun getClassOrInterfaceKeyword(): PsiElement? = findChildByType(TokenSet.create(JetTokens.CLASS_KEYWORD, JetTokens.INTERFACE_KEYWORD))
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi;
|
||||
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface JetClassOrObject extends PsiNameIdentifierOwner, JetDeclarationContainer, JetElement, JetModifierListOwner, JetNamedDeclaration {
|
||||
@Nullable
|
||||
JetDelegationSpecifierList getDelegationSpecifierList();
|
||||
|
||||
@NotNull
|
||||
List<JetDelegationSpecifier> getDelegationSpecifiers();
|
||||
|
||||
@NotNull
|
||||
List<JetClassInitializer> getAnonymousInitializers();
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
Name getNameAsName();
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
JetModifierList getModifierList();
|
||||
|
||||
@Nullable
|
||||
JetObjectDeclarationName getNameAsDeclaration();
|
||||
|
||||
@Nullable
|
||||
JetClassBody getBody();
|
||||
|
||||
boolean isTopLevel();
|
||||
|
||||
boolean isLocal();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.navigation.ItemPresentation
|
||||
import com.intellij.navigation.ItemPresentationProviders
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.stubs.IStubElementType
|
||||
import org.jetbrains.kotlin.JetNodeTypes
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
|
||||
|
||||
abstract public class JetClassOrObject : JetTypeParameterListOwnerStub<KotlinClassOrObjectStub<out JetClassOrObject>>, JetDeclarationContainer, JetNamedDeclaration {
|
||||
public constructor(node: ASTNode) : super(node)
|
||||
public constructor(stub: KotlinClassOrObjectStub<out JetClassOrObject>, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
|
||||
|
||||
public fun getDelegationSpecifierList(): JetDelegationSpecifierList? = getStubOrPsiChild(JetStubElementTypes.DELEGATION_SPECIFIER_LIST)
|
||||
open public fun getDelegationSpecifiers(): List<JetDelegationSpecifier> = getDelegationSpecifierList()?.getDelegationSpecifiers().orEmpty()
|
||||
|
||||
public fun getAnonymousInitializers(): List<JetClassInitializer> = getBody()?.getAnonymousInitializers().orEmpty()
|
||||
|
||||
public fun getNameAsDeclaration(): JetObjectDeclarationName? =
|
||||
findChildByType<PsiElement>(JetNodeTypes.OBJECT_DECLARATION_NAME) as JetObjectDeclarationName?
|
||||
|
||||
public fun getBody(): JetClassBody? = getStubOrPsiChild(JetStubElementTypes.CLASS_BODY)
|
||||
|
||||
public fun isTopLevel(): Boolean = getStub()?.isTopLevel() ?: (getParent() is JetFile)
|
||||
|
||||
public fun isLocal(): Boolean = getStub()?.isLocal() ?: JetPsiUtil.isLocal(this)
|
||||
|
||||
override fun getDeclarations() = getBody()?.getDeclarations().orEmpty()
|
||||
|
||||
override fun getPresentation(): ItemPresentation? = ItemPresentationProviders.getItemPresentation(this)
|
||||
|
||||
public fun getPrimaryConstructor(): JetPrimaryConstructor? = getStubOrPsiChild(JetStubElementTypes.PRIMARY_CONSTRUCTOR)
|
||||
|
||||
public fun getPrimaryConstructorModifierList(): JetModifierList? = getPrimaryConstructor()?.getModifierList()
|
||||
public fun getPrimaryConstructorParameterList(): JetParameterList? = getPrimaryConstructor()?.getValueParameterList()
|
||||
public fun getPrimaryConstructorParameters(): List<JetParameter> = getPrimaryConstructorParameterList()?.getParameters().orEmpty()
|
||||
|
||||
public fun hasExplicitPrimaryConstructor(): Boolean = getPrimaryConstructor() != null
|
||||
|
||||
public fun hasPrimaryConstructor(): Boolean = hasExplicitPrimaryConstructor() || !hasSecondaryConstructors()
|
||||
private fun hasSecondaryConstructors(): Boolean = !getSecondaryConstructors().isEmpty()
|
||||
|
||||
public fun getSecondaryConstructors(): List<JetSecondaryConstructor> = getBody()?.getSecondaryConstructors().orEmpty()
|
||||
|
||||
public fun isAnnotation(): Boolean = hasModifier(JetTokens.ANNOTATION_KEYWORD)
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.JetNodeType;
|
||||
|
||||
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
|
||||
import static org.jetbrains.kotlin.psi.PsiPackage.createExpressionByPattern;
|
||||
|
||||
public abstract class JetExpressionImpl extends JetElementImpl implements JetExpression {
|
||||
public JetExpressionImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitExpression(this, data);
|
||||
}
|
||||
|
||||
protected JetExpression findExpressionUnder(JetNodeType type) {
|
||||
JetContainerNode containerNode = (JetContainerNode) findChildByType(type);
|
||||
if (containerNode == null) return null;
|
||||
|
||||
return containerNode.findChildByClass(JetExpression.class);
|
||||
}
|
||||
|
||||
//NOTE: duplicate with JetExpressionImplStub
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException {
|
||||
PsiElement parent = getParent();
|
||||
if (parent instanceof JetExpression && newElement instanceof JetExpression &&
|
||||
JetPsiUtil.areParenthesesNecessary((JetExpression) newElement, this, (JetExpression) parent)) {
|
||||
return super.replace(createExpressionByPattern(JetPsiFactory(this), "($0)", newElement));
|
||||
}
|
||||
return super.replace(newElement);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.JetNodeType
|
||||
|
||||
public abstract class JetExpressionImpl(node: ASTNode) : JetElementImpl(node), JetExpression {
|
||||
|
||||
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D) = visitor.visitExpression(this, data)
|
||||
|
||||
protected fun findExpressionUnder(type: JetNodeType): JetExpression? {
|
||||
val containerNode = findChildByType<JetContainerNode>(type) ?: return null
|
||||
return containerNode.findChildByClass<JetExpression>(javaClass())
|
||||
}
|
||||
|
||||
override fun replace(newElement: PsiElement): PsiElement {
|
||||
return replaceExpression(this, newElement, { super<JetElementImpl>.replace(it) })
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun replaceExpression(expression: JetExpression, newElement: PsiElement, rawReplaceHandler: (PsiElement) -> PsiElement): PsiElement {
|
||||
val parent = expression.getParent()
|
||||
|
||||
if (newElement is JetExpression) {
|
||||
when (parent) {
|
||||
is JetExpression -> {
|
||||
if (JetPsiUtil.areParenthesesNecessary(newElement, expression, parent)) {
|
||||
return rawReplaceHandler(JetPsiFactory(expression).createExpressionByPattern("($0)", newElement))
|
||||
}
|
||||
}
|
||||
|
||||
is JetSimpleNameStringTemplateEntry -> {
|
||||
if (newElement !is JetSimpleNameExpression) {
|
||||
val newEntry = parent.replace(JetPsiFactory(expression).createBlockStringTemplateEntry(newElement)) as JetBlockStringTemplateEntry
|
||||
return newEntry.getExpression()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rawReplaceHandler(newElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,9 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.stubs.IStubElementType;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
|
||||
import static org.jetbrains.kotlin.psi.PsiPackage.createExpressionByPattern;
|
||||
|
||||
public abstract class JetExpressionImplStub<T extends StubElement> extends JetElementImplStub<T> implements JetExpression {
|
||||
public JetExpressionImplStub(@NotNull T stub, @NotNull IStubElementType nodeType) {
|
||||
super(stub, nodeType);
|
||||
@@ -40,15 +38,19 @@ public abstract class JetExpressionImplStub<T extends StubElement> extends JetEl
|
||||
return visitor.visitExpression(this, data);
|
||||
}
|
||||
|
||||
//NOTE: duplicate with JetExpressionImpl
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException {
|
||||
PsiElement parent = getParent();
|
||||
if (parent instanceof JetExpression && newElement instanceof JetExpression &&
|
||||
JetPsiUtil.areParenthesesNecessary((JetExpression) newElement, this, (JetExpression) parent)) {
|
||||
return super.replace(createExpressionByPattern(JetPsiFactory(this), "($0)", newElement));
|
||||
}
|
||||
return JetExpressionImpl.Companion.replaceExpression(this, newElement, new Function1<PsiElement, PsiElement>() {
|
||||
@Override
|
||||
public PsiElement invoke(PsiElement element) {
|
||||
return rawReplace(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiElement rawReplace(@NotNull PsiElement newElement) {
|
||||
return super.replace(newElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public final class JetNamedDeclarationUtil {
|
||||
return getFQName((JetNamedDeclaration) parent);
|
||||
}
|
||||
else if (namedDeclaration instanceof JetParameter) {
|
||||
JetClass constructorClass = JetPsiUtil.getClassIfParameterIsProperty((JetParameter) namedDeclaration);
|
||||
JetClassOrObject constructorClass = JetPsiUtil.getClassIfParameterIsProperty((JetParameter) namedDeclaration);
|
||||
if (constructorClass != null) {
|
||||
return getFQName(constructorClass);
|
||||
}
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.JetNodeTypes;
|
||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.name.SpecialNames;
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinObjectStub;
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JetObjectDeclaration extends JetNamedDeclarationStub<KotlinObjectStub> implements JetClassOrObject {
|
||||
public JetObjectDeclaration(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public JetObjectDeclaration(@NotNull KotlinObjectStub stub) {
|
||||
super(stub, JetStubElementTypes.OBJECT_DECLARATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
KotlinObjectStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.getName();
|
||||
}
|
||||
|
||||
JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
|
||||
if (nameAsDeclaration == null && isCompanion()) {
|
||||
//NOTE: a hack in PSI that simplifies writing frontend code
|
||||
return SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.toString();
|
||||
}
|
||||
return nameAsDeclaration == null ? null : nameAsDeclaration.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTopLevel() {
|
||||
KotlinObjectStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.isTopLevel();
|
||||
}
|
||||
|
||||
return getParent() instanceof JetFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getNameIdentifier() {
|
||||
JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
|
||||
return nameAsDeclaration == null ? null : nameAsDeclaration.getNameIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
|
||||
JetObjectDeclarationName declarationName = getNameAsDeclaration();
|
||||
if (declarationName == null) {
|
||||
JetPsiFactory psiFactory = new JetPsiFactory(getProject());
|
||||
PsiElement result = addAfter(psiFactory.createObjectDeclarationName(name), getObjectKeyword());
|
||||
addAfter(psiFactory.createWhiteSpace(), getObjectKeyword());
|
||||
|
||||
return result;
|
||||
} else {
|
||||
return declarationName.setName(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JetObjectDeclarationName getNameAsDeclaration() {
|
||||
return (JetObjectDeclarationName) findChildByType(JetNodeTypes.OBJECT_DECLARATION_NAME);
|
||||
}
|
||||
|
||||
public boolean isCompanion() {
|
||||
KotlinObjectStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.isCompanion();
|
||||
}
|
||||
return hasModifier(JetTokens.COMPANION_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
return modifierList != null && modifierList.hasModifier(modifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JetDelegationSpecifierList getDelegationSpecifierList() {
|
||||
return getStubOrPsiChild(JetStubElementTypes.DELEGATION_SPECIFIER_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetDelegationSpecifier> getDelegationSpecifiers() {
|
||||
JetDelegationSpecifierList list = getDelegationSpecifierList();
|
||||
return list != null ? list.getDelegationSpecifiers() : Collections.<JetDelegationSpecifier>emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetClassInitializer> getAnonymousInitializers() {
|
||||
JetClassBody body = getBody();
|
||||
if (body == null) return Collections.emptyList();
|
||||
|
||||
return body.getAnonymousInitializers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetClassBody getBody() {
|
||||
return getStubOrPsiChild(JetStubElementTypes.CLASS_BODY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
KotlinObjectStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.isLocal();
|
||||
}
|
||||
return JetPsiUtil.isLocal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextOffset() {
|
||||
PsiElement nameIdentifier = getNameIdentifier();
|
||||
if (nameIdentifier != null) {
|
||||
return nameIdentifier.getTextRange().getStartOffset();
|
||||
}
|
||||
else {
|
||||
return getObjectKeyword().getTextRange().getStartOffset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetDeclaration> getDeclarations() {
|
||||
JetClassBody body = getBody();
|
||||
if (body == null) return Collections.emptyList();
|
||||
|
||||
return body.getDeclarations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitObjectDeclaration(this, data);
|
||||
}
|
||||
|
||||
public boolean isObjectLiteral() {
|
||||
KotlinObjectStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.isObjectLiteral();
|
||||
}
|
||||
return getParent() instanceof JetObjectLiteralExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiElement getObjectKeyword() {
|
||||
return findChildByType(JetTokens.OBJECT_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return ItemPresentationProviders.getItemPresentation(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.navigation.ItemPresentation
|
||||
import com.intellij.navigation.ItemPresentationProviders
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinObjectStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.JetStubElementTypes
|
||||
|
||||
public class JetObjectDeclaration : JetClassOrObject {
|
||||
public constructor(node: ASTNode) : super(node)
|
||||
public constructor(stub: KotlinObjectStub) : super(stub, JetStubElementTypes.OBJECT_DECLARATION)
|
||||
|
||||
override fun getStub(): KotlinObjectStub? = super.getStub() as? KotlinObjectStub
|
||||
|
||||
override fun getName(): String? {
|
||||
val stub = getStub()
|
||||
if (stub != null) {
|
||||
return stub.getName()
|
||||
}
|
||||
|
||||
val nameAsDeclaration = getNameAsDeclaration()
|
||||
if (nameAsDeclaration == null && isCompanion()) {
|
||||
//NOTE: a hack in PSI that simplifies writing frontend code
|
||||
return SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.toString()
|
||||
}
|
||||
return nameAsDeclaration?.getName()
|
||||
}
|
||||
|
||||
override fun getNameIdentifier(): PsiElement? = getNameAsDeclaration()?.getNameIdentifier()
|
||||
|
||||
override fun setName(NonNls name: String): PsiElement {
|
||||
val declarationName = getNameAsDeclaration()
|
||||
if (declarationName == null) {
|
||||
val psiFactory = JetPsiFactory(getProject())
|
||||
val result = addAfter(psiFactory.createObjectDeclarationName(name), getObjectKeyword())
|
||||
addAfter(psiFactory.createWhiteSpace(), getObjectKeyword())
|
||||
|
||||
return result
|
||||
}
|
||||
else {
|
||||
return declarationName.setName(name)
|
||||
}
|
||||
}
|
||||
|
||||
public fun isCompanion(): Boolean = getStub()?.isCompanion() ?: hasModifier(JetTokens.COMPANION_KEYWORD)
|
||||
|
||||
override fun getTextOffset(): Int = getNameIdentifier()?.getTextRange()?.getStartOffset()
|
||||
?: getObjectKeyword().getTextRange().getStartOffset()
|
||||
|
||||
override fun <R, D> accept(visitor: JetVisitor<R, D>, data: D): R {
|
||||
return visitor.visitObjectDeclaration(this, data)
|
||||
}
|
||||
|
||||
public fun isObjectLiteral(): Boolean = getStub()?.isObjectLiteral() ?: (getParent() is JetObjectLiteralExpression)
|
||||
|
||||
public fun getObjectKeyword(): PsiElement = findChildByType(JetTokens.OBJECT_KEYWORD)
|
||||
}
|
||||
@@ -71,17 +71,9 @@ public class JetPrimaryConstructor extends JetDeclarationStub<KotlinPlaceHolderS
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetClass getContainingClassOrNull() {
|
||||
JetClassOrObject classOrObject = (JetClassOrObject) getParent();
|
||||
return classOrObject instanceof JetClass ? (JetClass) classOrObject : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetClass getContainingClass() {
|
||||
JetClass classOrNull = getContainingClassOrNull();
|
||||
assert classOrNull != null : "This method should be called when parent is JetClass";
|
||||
return classOrNull;
|
||||
public JetClassOrObject getContainingClassOrObject() {
|
||||
return (JetClassOrObject) getParent();
|
||||
}
|
||||
|
||||
public boolean hasConstructorKeyword() {
|
||||
|
||||
@@ -151,17 +151,9 @@ public class JetPsiFactory(private val project: Project) {
|
||||
|
||||
public fun createFile(fileName: String, text: String): JetFile {
|
||||
val file = doCreateFile(fileName, text)
|
||||
//TODO: KotlinInternalMode should be used here
|
||||
if (ApplicationManager.getApplication()!!.isInternal()) {
|
||||
val sw = StringWriter()
|
||||
Exception().printStackTrace(PrintWriter(sw))
|
||||
file.doNotAnalyze = "This file was created by JetPsiFactory and should not be analyzed. It was created at:\n" + sw.toString()
|
||||
}
|
||||
else {
|
||||
file.doNotAnalyze = "This file was created by JetPsiFactory and should not be analyzed\n" +
|
||||
"Enable kotlin internal mode get more info for debugging\n" +
|
||||
"Use createAnalyzableFile to create file that can be analyzed\n"
|
||||
}
|
||||
|
||||
file.doNotAnalyze = "This file was created by JetPsiFactory and should not be analyzed\n" +
|
||||
"Use createAnalyzableFile to create file that can be analyzed\n"
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
@@ -447,11 +447,11 @@ public class JetPsiUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetClass getClassIfParameterIsProperty(@NotNull JetParameter jetParameter) {
|
||||
public static JetClassOrObject getClassIfParameterIsProperty(@NotNull JetParameter jetParameter) {
|
||||
if (jetParameter.hasValOrVarNode()) {
|
||||
PsiElement grandParent = jetParameter.getParent().getParent();
|
||||
if (grandParent instanceof JetPrimaryConstructor) {
|
||||
return ((JetPrimaryConstructor) grandParent).getContainingClassOrNull();
|
||||
return ((JetPrimaryConstructor) grandParent).getContainingClassOrObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,7 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.renderName
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiChildRange
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.LinkedHashMap
|
||||
@@ -124,7 +121,7 @@ public fun <TElement : JetElement> createByPattern(pattern: String, vararg args:
|
||||
|
||||
for ((range, text) in placeholders) {
|
||||
val token = resultElement.findElementAt(range.getStartOffset())!!
|
||||
for (element in token.parents()) {
|
||||
for (element in token.parentsWithSelf) {
|
||||
val elementRange = element.getTextRange().shiftRight(-start)
|
||||
if (elementRange == range && expectedElementType.isInstance(element)) {
|
||||
val pointer = pointerManager.createSmartPsiElementPointer(element)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES 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.psi.psiUtil
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
public data class PsiChildRange(public val first: PsiElement?, public val last: PsiElement?) : Sequence<PsiElement> {
|
||||
init {
|
||||
if (first == null) {
|
||||
assert(last == null)
|
||||
}
|
||||
else {
|
||||
assert(first.getParent() == last!!.getParent())
|
||||
}
|
||||
}
|
||||
|
||||
public val isEmpty: Boolean
|
||||
get() = first == null
|
||||
|
||||
override fun iterator(): Iterator<PsiElement> {
|
||||
val sequence = if (first == null) {
|
||||
emptySequence<PsiElement>()
|
||||
}
|
||||
else {
|
||||
val afterLast = last!!.getNextSibling()
|
||||
first.siblings().takeWhile { it != afterLast }
|
||||
}
|
||||
return sequence.iterator()
|
||||
}
|
||||
|
||||
companion object {
|
||||
public val EMPTY: PsiChildRange = PsiChildRange(null, null)
|
||||
|
||||
public fun singleElement(element: PsiElement): PsiChildRange = PsiChildRange(element, element)
|
||||
}
|
||||
}
|
||||
@@ -17,26 +17,27 @@
|
||||
package org.jetbrains.kotlin.psi.psiUtil
|
||||
|
||||
import com.intellij.extapi.psi.StubBasedPsiElementBase
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.PsiSearchScopeUtil
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiParameter
|
||||
import com.intellij.psi.PsiParameterList
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.JetNodeTypes
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
// NOTE: in this file we collect only Kotlin-specific methods working with PSI and not modifying it
|
||||
|
||||
// ----------- Calls and qualified expressions ---------------------------------------------------------------------------------------------
|
||||
|
||||
public fun JetCallElement.getCallNameExpression(): JetSimpleNameExpression? {
|
||||
val calleeExpression = getCalleeExpression() ?: return null
|
||||
|
||||
@@ -47,92 +48,105 @@ public fun JetCallElement.getCallNameExpression(): JetSimpleNameExpression? {
|
||||
}
|
||||
}
|
||||
|
||||
public fun PsiElement.getParentOfTypesAndPredicate<T: PsiElement>(
|
||||
strict : Boolean = false, vararg parentClasses : Class<T>, predicate: (T) -> Boolean
|
||||
) : T? {
|
||||
var element = if (strict) getParent() else this
|
||||
while (element != null) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
when {
|
||||
(parentClasses.isEmpty() || parentClasses.any {parentClass -> parentClass.isInstance(element)}) && predicate(element!! as T) ->
|
||||
return element as T
|
||||
element is PsiFile ->
|
||||
return null
|
||||
else ->
|
||||
element = element!!.getParent()
|
||||
/**
|
||||
* Returns enclosing qualifying element for given [[JetSimpleNameExpression]]
|
||||
* ([[JetQualifiedExpression]] or [[JetUserType]] or original expression)
|
||||
*/
|
||||
public fun JetSimpleNameExpression.getQualifiedElement(): JetElement {
|
||||
val baseExpression: JetElement = (getParent() as? JetCallExpression) ?: this
|
||||
val parent = baseExpression.getParent()
|
||||
return when (parent) {
|
||||
is JetQualifiedExpression -> if (parent.getSelectorExpression().isAncestor(baseExpression)) parent else baseExpression
|
||||
is JetUserType -> if (parent.getReferenceExpression().isAncestor(baseExpression)) parent else baseExpression
|
||||
else -> baseExpression
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetSimpleNameExpression.getTopmostParentQualifiedExpressionForSelector(): JetQualifiedExpression? {
|
||||
return sequence<JetExpression>(this) {
|
||||
val parentQualified = it.getParent() as? JetQualifiedExpression
|
||||
if (parentQualified?.getSelectorExpression() == it) parentQualified else null
|
||||
}.last() as? JetQualifiedExpression
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns rightmost selector of the qualified element (null if there is no such selector)
|
||||
*/
|
||||
public fun JetElement.getQualifiedElementSelector(): JetElement? {
|
||||
return when (this) {
|
||||
is JetSimpleNameExpression -> this
|
||||
is JetCallExpression -> getCalleeExpression()
|
||||
is JetQualifiedExpression -> {
|
||||
val selector = getSelectorExpression()
|
||||
if (selector is JetCallExpression) selector.getCalleeExpression() else selector
|
||||
}
|
||||
is JetUserType -> getReferenceExpression()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetSimpleNameExpression.getReceiverExpression(): JetExpression? {
|
||||
val parent = getParent()
|
||||
when {
|
||||
parent is JetQualifiedExpression && !isImportDirectiveExpression() -> {
|
||||
val receiverExpression = parent.getReceiverExpression()
|
||||
// Name expression can't be receiver for itself
|
||||
if (receiverExpression != this) {
|
||||
return receiverExpression
|
||||
}
|
||||
}
|
||||
parent is JetCallExpression -> {
|
||||
//This is in case `a().b()`
|
||||
val callExpression = parent
|
||||
val grandParent = callExpression.getParent()
|
||||
if (grandParent is JetQualifiedExpression) {
|
||||
val parentsReceiver = grandParent.getReceiverExpression()
|
||||
if (parentsReceiver != callExpression) {
|
||||
return parentsReceiver
|
||||
}
|
||||
}
|
||||
}
|
||||
parent is JetBinaryExpression && parent.getOperationReference() == this -> {
|
||||
return if (parent.getOperationToken() in OperatorConventions.IN_OPERATIONS) parent.getRight() else parent.getLeft()
|
||||
}
|
||||
parent is JetUnaryExpression && parent.getOperationReference() == this -> {
|
||||
return parent.getBaseExpression()!!
|
||||
}
|
||||
parent is JetUserType -> {
|
||||
val qualifier = parent.getQualifier()
|
||||
if (qualifier != null) {
|
||||
return qualifier.getReferenceExpression()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
public fun PsiElement.getNonStrictParentOfType<T: PsiElement>(parentClass : Class<T>) : T? {
|
||||
return PsiTreeUtil.getParentOfType(this, parentClass, false)
|
||||
public fun JetElement.getQualifiedExpressionForSelector(): JetQualifiedExpression? {
|
||||
val parent = getParent()
|
||||
return if (parent is JetQualifiedExpression && parent.getSelectorExpression() == this) parent else null
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getParentOfType<reified T: PsiElement>(strict: Boolean): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, javaClass<T>(), strict)
|
||||
public fun JetElement.getQualifiedExpressionForSelectorOrThis(): JetElement {
|
||||
return getQualifiedExpressionForSelector() ?: this
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getStrictParentOfType<reified T: PsiElement>(): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, javaClass<T>(), true)
|
||||
public fun JetExpression.isDotReceiver(): Boolean =
|
||||
(getParent() as? JetDotQualifiedExpression)?.getReceiverExpression() == this
|
||||
|
||||
public fun JetElement.getCalleeHighlightingRange(): TextRange {
|
||||
val annotationEntry: JetAnnotationEntry =
|
||||
PsiTreeUtil.getParentOfType<JetAnnotationEntry>(
|
||||
this, javaClass<JetAnnotationEntry>(), /* strict = */false, javaClass<JetValueArgumentList>()
|
||||
) ?: return getTextRange()
|
||||
|
||||
val startOffset = annotationEntry.getAtSymbol()?.getTextRange()?.getStartOffset()
|
||||
?: annotationEntry.getCalleeExpression().startOffset
|
||||
|
||||
return TextRange(startOffset, annotationEntry.getCalleeExpression().endOffset)
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getNonStrictParentOfType<reified T: PsiElement>(): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, javaClass<T>(), false)
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getChildOfType<reified T: PsiElement>(): T? {
|
||||
return PsiTreeUtil.getChildOfType(this, javaClass<T>())
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getChildrenOfType<reified T: PsiElement>(): Array<T> {
|
||||
return PsiTreeUtil.getChildrenOfType(this, javaClass<T>()) ?: arrayOf()
|
||||
}
|
||||
|
||||
public fun PsiElement.getNextSiblingIgnoringWhitespaceAndComments(): PsiElement? {
|
||||
var current = this
|
||||
do {
|
||||
current = current.getNextSibling()
|
||||
if (current == null) return null
|
||||
}
|
||||
while (current is PsiComment || current is PsiWhiteSpace)
|
||||
return current
|
||||
}
|
||||
|
||||
public fun PsiElement?.isAncestor(element: PsiElement, strict: Boolean = false): Boolean {
|
||||
return PsiTreeUtil.isAncestor(this, element, strict)
|
||||
}
|
||||
|
||||
public fun <T: PsiElement> T.getIfChildIsInBranch(element: PsiElement, branch: T.() -> PsiElement?): T? {
|
||||
return if (branch().isAncestor(element)) this else null
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getParentOfTypeAndBranch<reified T: PsiElement>(strict: Boolean = false, noinline branch: T.() -> PsiElement?) : T? {
|
||||
return getParentOfType<T>(strict)?.getIfChildIsInBranch(this, branch)
|
||||
}
|
||||
|
||||
public fun JetClassOrObject.effectiveDeclarations(): List<JetDeclaration> =
|
||||
when(this) {
|
||||
is JetClass ->
|
||||
getDeclarations() + getPrimaryConstructorParameters().filter { p -> p.hasValOrVarNode() }
|
||||
else ->
|
||||
getDeclarations()
|
||||
}
|
||||
|
||||
public fun JetClass.isAbstract(): Boolean = isInterface() || hasModifier(JetTokens.ABSTRACT_KEYWORD)
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
public inline fun <reified T: PsiElement> PsiElement.replaced(newElement: T): T {
|
||||
val result = replace(newElement)
|
||||
return if (result is T)
|
||||
result
|
||||
else
|
||||
(result as JetParenthesizedExpression).getExpression() as T
|
||||
}
|
||||
|
||||
@suppress("UNCHECKED_CAST")
|
||||
public fun <T: PsiElement> T.copied(): T = copy() as T
|
||||
// ---------- Block expression -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public fun JetElement.blockExpressionsOrSingle(): Sequence<JetElement> =
|
||||
if (this is JetBlockExpression) getStatements().asSequence() else sequenceOf(this)
|
||||
@@ -140,31 +154,46 @@ public fun JetElement.blockExpressionsOrSingle(): Sequence<JetElement> =
|
||||
public fun JetExpression.lastBlockStatementOrThis(): JetExpression
|
||||
= (this as? JetBlockExpression)?.getStatements()?.lastIsInstanceOrNull<JetExpression>() ?: this
|
||||
|
||||
public fun JetBlockExpression.appendElement(element: JetElement): JetElement {
|
||||
public fun JetBlockExpression.contentRange(): PsiChildRange {
|
||||
val first = (getLBrace()?.getNextSibling() ?: getFirstChild())
|
||||
?.siblings(withItself = false)
|
||||
?.firstOrNull { it !is PsiWhiteSpace }
|
||||
val rBrace = getRBrace()
|
||||
val anchor = if (rBrace == null) {
|
||||
val lastChild = getLastChild()
|
||||
if (lastChild !is PsiWhiteSpace) addAfter(JetPsiFactory(this).createNewLine(), lastChild)!! else lastChild
|
||||
}
|
||||
else {
|
||||
rBrace.getPrevSibling()!!
|
||||
}
|
||||
return addAfter(element, anchor)!! as JetElement
|
||||
if (first == rBrace) return PsiChildRange.EMPTY
|
||||
val last = rBrace!!
|
||||
.siblings(forward = false, withItself = false)
|
||||
.first { it !is PsiWhiteSpace }
|
||||
return PsiChildRange(first, last)
|
||||
}
|
||||
|
||||
public fun JetElement.wrapInBlock(): JetBlockExpression {
|
||||
val block = JetPsiFactory(this).createEmptyBody()
|
||||
block.appendElement(this)
|
||||
return block
|
||||
// ----------- Inheritance -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public fun JetClass.isInheritable(): Boolean {
|
||||
return isInterface() || hasModifier(JetTokens.OPEN_KEYWORD) || hasModifier(JetTokens.ABSTRACT_KEYWORD)
|
||||
}
|
||||
|
||||
public fun JetDeclaration.isOverridable(): Boolean {
|
||||
val parent = getParent()
|
||||
if (!(parent is JetClassBody || parent is JetParameterList)) return false
|
||||
|
||||
val klass = parent.getParent()
|
||||
if (!(klass is JetClass && klass.isInheritable())) return false
|
||||
|
||||
if (hasModifier(JetTokens.FINAL_KEYWORD) || hasModifier(JetTokens.PRIVATE_KEYWORD)) return false
|
||||
|
||||
return klass.isInterface() ||
|
||||
hasModifier(JetTokens.ABSTRACT_KEYWORD) || hasModifier(JetTokens.OPEN_KEYWORD) || hasModifier(JetTokens.OVERRIDE_KEYWORD)
|
||||
}
|
||||
|
||||
public fun JetClass.isAbstract(): Boolean = isInterface() || hasModifier(JetTokens.ABSTRACT_KEYWORD)
|
||||
|
||||
/**
|
||||
* Returns the list of unqualified names that are indexed as the superclass names of this class. For the names that might be imported
|
||||
* via an aliased import, includes both the original and the aliased name (reference resolution during inheritor search will sort this out).
|
||||
*
|
||||
* @return the list of possible superclass names
|
||||
*/
|
||||
public fun <T: JetClassOrObject> StubBasedPsiElementBase<out KotlinClassOrObjectStub<T>>.getSuperNames(): List<String> {
|
||||
public fun StubBasedPsiElementBase<out KotlinClassOrObjectStub<out JetClassOrObject>>.getSuperNames(): List<String> {
|
||||
fun addSuperName(result: MutableList<String>, referencedName: String): Unit {
|
||||
result.add(referencedName)
|
||||
|
||||
@@ -207,342 +236,47 @@ public fun <T: JetClassOrObject> StubBasedPsiElementBase<out KotlinClassOrObject
|
||||
return result
|
||||
}
|
||||
|
||||
public fun SearchScope.contains(element: PsiElement): Boolean = PsiSearchScopeUtil.isInScope(this, element)
|
||||
// ------------ Annotations ----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public fun JetClass.isInheritable(): Boolean {
|
||||
return isInterface() || hasModifier(JetTokens.OPEN_KEYWORD) || hasModifier(JetTokens.ABSTRACT_KEYWORD)
|
||||
}
|
||||
|
||||
public fun JetDeclaration.isOverridable(): Boolean {
|
||||
val parent = getParent()
|
||||
if (!(parent is JetClassBody || parent is JetParameterList)) return false
|
||||
|
||||
val klass = parent.getParent()
|
||||
if (!(klass is JetClass && klass.isInheritable())) return false
|
||||
|
||||
if (hasModifier(JetTokens.FINAL_KEYWORD) || hasModifier(JetTokens.PRIVATE_KEYWORD)) return false
|
||||
|
||||
return klass.isInterface() ||
|
||||
hasModifier(JetTokens.ABSTRACT_KEYWORD) || hasModifier(JetTokens.OPEN_KEYWORD) || hasModifier(JetTokens.OVERRIDE_KEYWORD)
|
||||
}
|
||||
|
||||
public fun PsiElement.isExtensionDeclaration(): Boolean {
|
||||
val callable: JetCallableDeclaration? = when (this) {
|
||||
is JetNamedFunction, is JetProperty -> this as JetCallableDeclaration
|
||||
is JetPropertyAccessor -> getNonStrictParentOfType<JetProperty>()
|
||||
else -> null
|
||||
}
|
||||
|
||||
return callable?.getReceiverTypeReference() != null
|
||||
}
|
||||
|
||||
public fun PsiElement.isObjectLiteral(): Boolean = this is JetObjectDeclaration && isObjectLiteral()
|
||||
|
||||
//TODO: git rid of this method
|
||||
public fun PsiElement.deleteElementAndCleanParent() {
|
||||
val parent = getParent()
|
||||
|
||||
deleteElementWithDelimiters(this)
|
||||
deleteChildlessElement(parent, this.javaClass)
|
||||
}
|
||||
|
||||
// Delete element if it doesn't contain children of a given type
|
||||
private fun <T : PsiElement> deleteChildlessElement(element: PsiElement, childClass: Class<T>) {
|
||||
if (PsiTreeUtil.getChildrenOfType<T>(element, childClass) == null) {
|
||||
element.delete()
|
||||
}
|
||||
}
|
||||
|
||||
// Delete given element and all the elements separating it from the neighboring elements of the same class
|
||||
private fun deleteElementWithDelimiters(element: PsiElement) {
|
||||
val paramBefore = PsiTreeUtil.getPrevSiblingOfType<PsiElement>(element, element.javaClass)
|
||||
|
||||
val from: PsiElement
|
||||
val to: PsiElement
|
||||
if (paramBefore != null) {
|
||||
from = paramBefore.getNextSibling()
|
||||
to = element
|
||||
}
|
||||
else {
|
||||
val paramAfter = PsiTreeUtil.getNextSiblingOfType<PsiElement>(element, element.javaClass)
|
||||
|
||||
from = element
|
||||
to = if (paramAfter != null) paramAfter.getPrevSibling() else element
|
||||
}
|
||||
|
||||
val parent = element.getParent()
|
||||
|
||||
parent.deleteChildRange(from, to)
|
||||
}
|
||||
|
||||
|
||||
public fun PsiElement.parameterIndex(): Int {
|
||||
val parent = getParent()
|
||||
return when {
|
||||
this is JetParameter && parent is JetParameterList -> parent.getParameters().indexOf(this)
|
||||
this is PsiParameter && parent is PsiParameterList -> parent.getParameterIndex(this)
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns enclosing qualifying element for given [[JetSimpleNameExpression]]
|
||||
* ([[JetQualifiedExpression]] or [[JetUserType]] or original expression)
|
||||
*/
|
||||
public fun JetSimpleNameExpression.getQualifiedElement(): JetElement {
|
||||
val baseExpression: JetElement = (getParent() as? JetCallExpression) ?: this
|
||||
val parent = baseExpression.getParent()
|
||||
return when (parent) {
|
||||
is JetQualifiedExpression -> if (parent.getSelectorExpression().isAncestor(baseExpression)) parent else baseExpression
|
||||
is JetUserType -> if (parent.getReferenceExpression().isAncestor(baseExpression)) parent else baseExpression
|
||||
else -> baseExpression
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetSimpleNameExpression.getTopmostParentQualifiedExpressionForSelector(): JetQualifiedExpression? {
|
||||
return sequence<JetExpression>(this) {
|
||||
val parentQualified = it.getParent() as? JetQualifiedExpression
|
||||
if (parentQualified?.getSelectorExpression() == it) parentQualified else null
|
||||
}.last() as? JetQualifiedExpression
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns rightmost selector of the qualified element (null if there is no such selector)
|
||||
*/
|
||||
public fun JetElement.getQualifiedElementSelector(): JetElement? {
|
||||
return when (this) {
|
||||
is JetSimpleNameExpression -> this
|
||||
is JetCallExpression -> getCalleeExpression()
|
||||
is JetQualifiedExpression -> {
|
||||
val selector = getSelectorExpression()
|
||||
if (selector is JetCallExpression) selector.getCalleeExpression() else selector
|
||||
}
|
||||
is JetUserType -> getReferenceExpression()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns outermost qualified element ([[JetQualifiedExpression]] or [[JetUserType]]) in the non-interleaving chain
|
||||
* of qualified elements which enclose given expression
|
||||
* If there is no such elements original expression is returned
|
||||
*/
|
||||
public fun JetSimpleNameExpression.getOutermostNonInterleavingQualifiedElement(): JetElement {
|
||||
var element = ((getParent() as? JetCallExpression) ?: this).getParent()
|
||||
if (element !is JetQualifiedExpression && element !is JetUserType) return this
|
||||
|
||||
while (true) {
|
||||
val parent = element!!.getParent()
|
||||
if (parent !is JetQualifiedExpression && parent !is JetUserType) return element as JetElement
|
||||
element = parent
|
||||
}
|
||||
}
|
||||
|
||||
public fun PsiDirectory.getPackage(): PsiPackage? = JavaDirectoryService.getInstance()!!.getPackage(this)
|
||||
|
||||
public fun JetModifierListOwner.isPrivate(): Boolean = hasModifier(JetTokens.PRIVATE_KEYWORD)
|
||||
|
||||
public fun PsiElement.isInsideOf(elements: Iterable<PsiElement>): Boolean = elements.any { it.isAncestor(this) }
|
||||
|
||||
public tailRecursive fun PsiElement.getOutermostParentContainedIn(container: PsiElement): PsiElement? {
|
||||
val parent = getParent()
|
||||
return if (parent == container) this else parent?.getOutermostParentContainedIn(container)
|
||||
}
|
||||
|
||||
public fun JetSimpleNameExpression.getReceiverExpression(): JetExpression? {
|
||||
val parent = getParent()
|
||||
when {
|
||||
parent is JetQualifiedExpression && !isImportDirectiveExpression() -> {
|
||||
val receiverExpression = parent.getReceiverExpression()
|
||||
// Name expression can't be receiver for itself
|
||||
if (receiverExpression != this) {
|
||||
return receiverExpression
|
||||
}
|
||||
}
|
||||
parent is JetCallExpression -> {
|
||||
//This is in case `a().b()`
|
||||
val callExpression = parent
|
||||
val grandParent = callExpression.getParent()
|
||||
if (grandParent is JetQualifiedExpression) {
|
||||
val parentsReceiver = grandParent.getReceiverExpression()
|
||||
if (parentsReceiver != callExpression) {
|
||||
return parentsReceiver
|
||||
}
|
||||
}
|
||||
}
|
||||
parent is JetBinaryExpression && parent.getOperationReference() == this -> {
|
||||
return if (parent.getOperationToken() in OperatorConventions.IN_OPERATIONS) parent.getRight() else parent.getLeft()
|
||||
}
|
||||
parent is JetUnaryExpression && parent.getOperationReference() == this -> {
|
||||
return parent.getBaseExpression()!!
|
||||
}
|
||||
parent is JetUserType -> {
|
||||
val qualifier = parent.getQualifier()
|
||||
if (qualifier != null) {
|
||||
return qualifier.getReferenceExpression()!!
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
public fun JetSimpleNameExpression.isImportDirectiveExpression(): Boolean {
|
||||
val parent = getParent()
|
||||
if (parent == null) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
return parent is JetImportDirective || parent.getParent() is JetImportDirective
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetElement.getTextWithLocation(): String = "'${this.getText()}' at ${DiagnosticUtils.atLocation(this)}"
|
||||
|
||||
public fun JetExpression.isFunctionLiteralOutsideParentheses(): Boolean {
|
||||
// Annotations on labeled expression lies on it's base expression
|
||||
public fun JetExpression.getAnnotationEntries(): List<JetAnnotationEntry> {
|
||||
val parent = getParent()
|
||||
return when (parent) {
|
||||
is JetFunctionLiteralArgument -> true
|
||||
is JetLabeledExpression -> parent.isFunctionLiteralOutsideParentheses()
|
||||
else -> false
|
||||
is JetAnnotatedExpression -> parent.getAnnotationEntries()
|
||||
is JetLabeledExpression -> parent.getAnnotationEntries()
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
}
|
||||
}
|
||||
|
||||
public fun PsiElement.siblings(forward: Boolean = true, withItself: Boolean = true): Sequence<PsiElement> {
|
||||
val stepFun = if (forward) { e: PsiElement -> e.getNextSibling() } else { e: PsiElement -> e.getPrevSibling() }
|
||||
val sequence = sequence(this, stepFun)
|
||||
return if (withItself) sequence else sequence.drop(1)
|
||||
}
|
||||
|
||||
public fun ASTNode.siblings(forward: Boolean = true, withItself: Boolean = true): Sequence<ASTNode> {
|
||||
val stepFun = if (forward) { node: ASTNode -> node.getTreeNext() } else { e: ASTNode -> e.getTreeNext() }
|
||||
val sequence = sequence(this, stepFun)
|
||||
return if (withItself) sequence else sequence.drop(1)
|
||||
}
|
||||
|
||||
public fun PsiElement.parents(withItself: Boolean = true): Sequence<PsiElement> {
|
||||
val sequence = sequence(this) { if (it is PsiFile) null else it.getParent() }
|
||||
return if (withItself) sequence else sequence.drop(1)
|
||||
}
|
||||
|
||||
public fun ASTNode.parents(withItself: Boolean = true): Sequence<ASTNode> {
|
||||
val sequence = sequence(this) { it.getTreeParent() }
|
||||
return if (withItself) sequence else sequence.drop(1)
|
||||
}
|
||||
|
||||
public fun JetExpression.getAssignmentByLHS(): JetBinaryExpression? {
|
||||
val parent = getParent() as? JetBinaryExpression ?: return null
|
||||
return if (JetPsiUtil.isAssignment(parent) && parent.getLeft() == this) parent else null
|
||||
}
|
||||
|
||||
public fun PsiElement.prevLeaf(skipEmptyElements: Boolean = false): PsiElement?
|
||||
= PsiTreeUtil.prevLeaf(this, skipEmptyElements)
|
||||
|
||||
public fun PsiElement.nextLeaf(skipEmptyElements: Boolean = false): PsiElement?
|
||||
= PsiTreeUtil.nextLeaf(this, skipEmptyElements)
|
||||
|
||||
public fun PsiElement.prevLeaf(filter: (PsiElement) -> Boolean): PsiElement? {
|
||||
var leaf = prevLeaf()
|
||||
while (leaf != null && !filter(leaf)) {
|
||||
leaf = leaf.prevLeaf()
|
||||
public fun JetAnnotationsContainer.collectAnnotationEntriesFromStubOrPsi(): List<JetAnnotationEntry> {
|
||||
return when (this) {
|
||||
is StubBasedPsiElementBase<*> -> getStub()?.collectAnnotationEntriesFromStubElement() ?: collectAnnotationEntriesFromPsi()
|
||||
else -> collectAnnotationEntriesFromPsi()
|
||||
}
|
||||
return leaf
|
||||
}
|
||||
|
||||
public fun PsiElement.nextLeaf(filter: (PsiElement) -> Boolean): PsiElement? {
|
||||
var leaf = nextLeaf()
|
||||
while (leaf != null && !filter(leaf)) {
|
||||
leaf = leaf.nextLeaf()
|
||||
}
|
||||
return leaf
|
||||
}
|
||||
|
||||
public fun JetExpression.isDotReceiver(): Boolean =
|
||||
(getParent() as? JetDotQualifiedExpression)?.getReceiverExpression() == this
|
||||
|
||||
public fun Call.isSafeCall(): Boolean {
|
||||
if (this is CallForImplicitInvoke) {
|
||||
//implicit safe 'invoke'
|
||||
if (getOuterCall().isExplicitSafeCall()) {
|
||||
return true
|
||||
private fun StubElement<*>.collectAnnotationEntriesFromStubElement(): List<JetAnnotationEntry> {
|
||||
return getChildrenStubs().flatMap {
|
||||
child ->
|
||||
when (child.getStubType()) {
|
||||
JetNodeTypes.ANNOTATION_ENTRY -> listOf(child.getPsi() as JetAnnotationEntry)
|
||||
JetNodeTypes.ANNOTATION -> (child.getPsi() as JetAnnotation).getEntries()
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
}
|
||||
}
|
||||
return isExplicitSafeCall()
|
||||
}
|
||||
|
||||
public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS
|
||||
|
||||
public fun JetStringTemplateExpression.getContentRange(): TextRange {
|
||||
val start = getNode().getFirstChildNode().getTextLength()
|
||||
val lastChild = getNode().getLastChildNode()
|
||||
val length = getTextLength()
|
||||
return TextRange(start, if (lastChild.getElementType() == JetTokens.CLOSING_QUOTE) length - lastChild.getTextLength() else length)
|
||||
}
|
||||
|
||||
public fun JetStringTemplateExpression.isSingleQuoted(): Boolean
|
||||
= getNode().getFirstChildNode().getTextLength() == 1
|
||||
|
||||
public fun PsiFile.elementsInRange(range: TextRange): List<PsiElement> {
|
||||
var offset = range.getStartOffset()
|
||||
val result = ArrayList<PsiElement>()
|
||||
while (offset < range.getEndOffset()) {
|
||||
val currentRange = TextRange(offset, range.getEndOffset())
|
||||
val leaf = findFirstLeafWhollyInRange(this, currentRange) ?: break
|
||||
|
||||
val element = leaf
|
||||
.parents(withItself = true)
|
||||
.first {
|
||||
val parent = it.getParent()
|
||||
it is PsiFile || parent.getTextRange() !in currentRange
|
||||
}
|
||||
result.add(element)
|
||||
|
||||
offset = element.endOffset
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findFirstLeafWhollyInRange(file: PsiFile, range: TextRange): PsiElement? {
|
||||
var element = file.findElementAt(range.getStartOffset()) ?: return null
|
||||
var elementRange = element.getTextRange()
|
||||
if (elementRange.getStartOffset() < range.getStartOffset()) {
|
||||
element = element.nextLeaf(skipEmptyElements = true) ?: return null
|
||||
elementRange = element.getTextRange()
|
||||
}
|
||||
assert(elementRange.getStartOffset() >= range.getStartOffset())
|
||||
return if (elementRange.getEndOffset() <= range.getEndOffset()) element else null
|
||||
}
|
||||
|
||||
fun JetNamedDeclaration.getValueParameters(): List<JetParameter> {
|
||||
return getValueParameterList()?.getParameters() ?: Collections.emptyList()
|
||||
}
|
||||
|
||||
fun JetNamedDeclaration.getValueParameterList(): JetParameterList? {
|
||||
return when (this) {
|
||||
is JetCallableDeclaration -> getValueParameterList()
|
||||
is JetClass -> getPrimaryConstructorParameterList()
|
||||
else -> null
|
||||
private fun JetAnnotationsContainer.collectAnnotationEntriesFromPsi(): List<JetAnnotationEntry> {
|
||||
return getChildren().flatMap { child ->
|
||||
when (child) {
|
||||
is JetAnnotationEntry -> listOf(child)
|
||||
is JetAnnotation -> child.getEntries()
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun PsiElement.getElementTextWithContext(): String {
|
||||
if (this is PsiFile) {
|
||||
return getContainingFile().getText()
|
||||
}
|
||||
|
||||
// Find parent for element among file children
|
||||
val topLevelElement = PsiTreeUtil.findFirstParent(this, { it.getParent() is PsiFile }) ?:
|
||||
throw AssertionError("For non-file element we should always be able to find parent in file children")
|
||||
|
||||
val startContextOffset = topLevelElement.startOffset
|
||||
val elementContextOffset = getTextRange().getStartOffset()
|
||||
|
||||
val inFileParentOffset = elementContextOffset - startContextOffset
|
||||
|
||||
return StringBuilder(topLevelElement.getText())
|
||||
.insert(inFileParentOffset, "<caret>")
|
||||
.insert(0, "File name: ${getContainingFile().getName()}\n")
|
||||
.toString()
|
||||
}
|
||||
// -------- Recursive tree visiting --------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Calls `block` on each descendant of T type
|
||||
// Note, that calls happen in order of DFS-exit, so deeper nodes are applied earlier
|
||||
@@ -561,118 +295,81 @@ public inline fun <reified T : JetElement, R> flatMapDescendantsOfTypeVisitor(ac
|
||||
return forEachDescendantOfTypeVisitor<T> { accumulator.addAll(map(it)) }
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(noinline action: (T) -> Unit) {
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
super.visitElement(element)
|
||||
if (element is T) {
|
||||
action(element)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// ----------- Other -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean = { true }): Boolean {
|
||||
return findDescendantOfType(predicate) != null
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(noinline predicate: (T) -> Boolean = { true }): T? {
|
||||
var result: T? = null
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (result != null) return
|
||||
if (element is T && predicate(element)) {
|
||||
result = element
|
||||
return
|
||||
}
|
||||
super.visitElement(element)
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> {
|
||||
val result = ArrayList<T>()
|
||||
forEachDescendantOfType<T> {
|
||||
if (predicate(it)) {
|
||||
result.add(it)
|
||||
}
|
||||
public fun JetClassOrObject.effectiveDeclarations(): List<JetDeclaration> {
|
||||
return when(this) {
|
||||
is JetClass -> getDeclarations() + getPrimaryConstructorParameters().filter { p -> p.hasValOrVarNode() }
|
||||
else -> getDeclarations()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public fun PsiFile.getFqNameByDirectory(): FqName {
|
||||
val qualifiedNameByDirectory = getParent()?.getPackage()?.getQualifiedName()
|
||||
return qualifiedNameByDirectory?.let { FqName(it) } ?: FqName.ROOT
|
||||
}
|
||||
|
||||
public fun JetFile.packageMatchesDirectory(): Boolean = getPackageFqName() == getFqNameByDirectory()
|
||||
|
||||
public fun JetAnnotationsContainer.collectAnnotationEntriesFromStubOrPsi(): List<JetAnnotationEntry> =
|
||||
when (this) {
|
||||
is StubBasedPsiElementBase<*> -> getStub()?.collectAnnotationEntriesFromStubElement() ?: collectAnnotationEntriesFromPsi()
|
||||
else -> collectAnnotationEntriesFromPsi()
|
||||
public fun JetDeclaration.isExtensionDeclaration(): Boolean {
|
||||
val callable: JetCallableDeclaration? = when (this) {
|
||||
is JetNamedFunction, is JetProperty -> this as JetCallableDeclaration
|
||||
is JetPropertyAccessor -> getNonStrictParentOfType<JetProperty>()
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun StubElement<*>.collectAnnotationEntriesFromStubElement() =
|
||||
getChildrenStubs().flatMap {
|
||||
child ->
|
||||
when (child.getStubType()) {
|
||||
JetNodeTypes.ANNOTATION_ENTRY -> listOf(child.getPsi() as JetAnnotationEntry)
|
||||
JetNodeTypes.ANNOTATION -> (child.getPsi() as JetAnnotation).getEntries()
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
}
|
||||
}
|
||||
|
||||
private fun JetAnnotationsContainer.collectAnnotationEntriesFromPsi() =
|
||||
getChildren().flatMap {
|
||||
child ->
|
||||
when (child) {
|
||||
is JetAnnotationEntry -> listOf(child)
|
||||
is JetAnnotation -> child.getEntries()
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetElement.getCalleeHighlightingRange(): TextRange {
|
||||
val annotationEntry: JetAnnotationEntry =
|
||||
PsiTreeUtil.getParentOfType<JetAnnotationEntry>(
|
||||
this, javaClass<JetAnnotationEntry>(), /* strict = */false, javaClass<JetValueArgumentList>()
|
||||
) ?: return getTextRange()
|
||||
|
||||
val startOffset = annotationEntry.getAtSymbol()?.getTextRange()?.getStartOffset()
|
||||
?: annotationEntry.getCalleeExpression().startOffset
|
||||
|
||||
return TextRange(startOffset, annotationEntry.getCalleeExpression().endOffset)
|
||||
return callable?.getReceiverTypeReference() != null
|
||||
}
|
||||
|
||||
public fun JetBlockExpression.contentRange(): PsiChildRange {
|
||||
val first = (getLBrace()?.getNextSibling() ?: getFirstChild())
|
||||
?.siblings(withItself = false)
|
||||
?.firstOrNull { it !is PsiWhiteSpace }
|
||||
val rBrace = getRBrace()
|
||||
if (first == rBrace) return PsiChildRange.EMPTY
|
||||
val last = rBrace!!
|
||||
.siblings(forward = false, withItself = false)
|
||||
.first { it !is PsiWhiteSpace }
|
||||
return PsiChildRange(first, last)
|
||||
public fun JetClassOrObject.isObjectLiteral(): Boolean = this is JetObjectDeclaration && isObjectLiteral()
|
||||
|
||||
//TODO: strange method, and not only Kotlin specific (also Java)
|
||||
public fun PsiElement.parameterIndex(): Int {
|
||||
val parent = getParent()
|
||||
return when {
|
||||
this is JetParameter && parent is JetParameterList -> parent.getParameters().indexOf(this)
|
||||
this is PsiParameter && parent is PsiParameterList -> parent.getParameterIndex(this)
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
// Annotations on labeled expression lies on it's base expression
|
||||
public fun JetExpression.getAnnotationEntries(): List<JetAnnotationEntry> {
|
||||
public fun JetModifierListOwner.isPrivate(): Boolean = hasModifier(JetTokens.PRIVATE_KEYWORD)
|
||||
|
||||
public fun JetSimpleNameExpression.isImportDirectiveExpression(): Boolean {
|
||||
val parent = getParent()
|
||||
if (parent == null) {
|
||||
return false
|
||||
}
|
||||
else {
|
||||
return parent is JetImportDirective || parent.getParent() is JetImportDirective
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetExpression.isFunctionLiteralOutsideParentheses(): Boolean {
|
||||
val parent = getParent()
|
||||
return when (parent) {
|
||||
is JetAnnotatedExpression -> parent.getAnnotationEntries()
|
||||
is JetLabeledExpression -> parent.getAnnotationEntries()
|
||||
else -> emptyList<JetAnnotationEntry>()
|
||||
is JetFunctionLiteralArgument -> true
|
||||
is JetLabeledExpression -> parent.isFunctionLiteralOutsideParentheses()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
public fun JetElement.getQualifiedExpressionForSelector(): JetQualifiedExpression? {
|
||||
val parent = getParent()
|
||||
return if (parent is JetQualifiedExpression && parent.getSelectorExpression() == this) parent else null
|
||||
public fun JetExpression.getAssignmentByLHS(): JetBinaryExpression? {
|
||||
val parent = getParent() as? JetBinaryExpression ?: return null
|
||||
return if (JetPsiUtil.isAssignment(parent) && parent.getLeft() == this) parent else null
|
||||
}
|
||||
|
||||
public fun JetElement.getQualifiedExpressionForSelectorOrThis(): JetElement {
|
||||
return getQualifiedExpressionForSelector() ?: this
|
||||
}
|
||||
public fun JetStringTemplateExpression.getContentRange(): TextRange {
|
||||
val start = getNode().getFirstChildNode().getTextLength()
|
||||
val lastChild = getNode().getLastChildNode()
|
||||
val length = getTextLength()
|
||||
return TextRange(start, if (lastChild.getElementType() == JetTokens.CLOSING_QUOTE) length - lastChild.getTextLength() else length)
|
||||
}
|
||||
|
||||
public fun JetStringTemplateExpression.isSingleQuoted(): Boolean
|
||||
= getNode().getFirstChildNode().getTextLength() == 1
|
||||
|
||||
public fun JetNamedDeclaration.getValueParameters(): List<JetParameter> {
|
||||
return getValueParameterList()?.getParameters() ?: Collections.emptyList()
|
||||
}
|
||||
|
||||
public fun JetNamedDeclaration.getValueParameterList(): JetParameterList? {
|
||||
return when (this) {
|
||||
is JetCallableDeclaration -> getValueParameterList()
|
||||
is JetClass -> getPrimaryConstructorParameterList()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,188 @@
|
||||
package org.jetbrains.kotlin.psi.psiUtil
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.PsiSearchScopeUtil
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||
import java.util.ArrayList
|
||||
|
||||
//TODO: move here more functions from jetPsiUtil.kt
|
||||
// NOTE: in this file we collect only LANGUAGE INDEPENDENT methods working with PSI and not modifying it
|
||||
|
||||
// ----------- Walking children/siblings/parents -------------------------------------------------------------------------------------------
|
||||
|
||||
public val PsiElement.allChildren: PsiChildRange
|
||||
get() {
|
||||
val first = getFirstChild()
|
||||
return if (first != null) PsiChildRange(first, getLastChild()) else PsiChildRange.EMPTY
|
||||
}
|
||||
public fun PsiElement.siblings(forward: Boolean = true, withItself: Boolean = true): Sequence<PsiElement> {
|
||||
val stepFun = if (forward) { e: PsiElement -> e.getNextSibling() } else { e: PsiElement -> e.getPrevSibling() }
|
||||
val sequence = sequence(this, stepFun)
|
||||
return if (withItself) sequence else sequence.drop(1)
|
||||
}
|
||||
|
||||
public val PsiElement.parentsWithSelf: Sequence<PsiElement>
|
||||
get() = sequence(this) { if (it is PsiFile) null else it.getParent() }
|
||||
|
||||
public val PsiElement.parents: Sequence<PsiElement>
|
||||
get() = parentsWithSelf.drop(1)
|
||||
|
||||
public fun PsiElement.prevLeaf(skipEmptyElements: Boolean = false): PsiElement?
|
||||
= PsiTreeUtil.prevLeaf(this, skipEmptyElements)
|
||||
|
||||
public fun PsiElement.nextLeaf(skipEmptyElements: Boolean = false): PsiElement?
|
||||
= PsiTreeUtil.nextLeaf(this, skipEmptyElements)
|
||||
|
||||
public fun PsiElement.prevLeaf(filter: (PsiElement) -> Boolean): PsiElement? {
|
||||
var leaf = prevLeaf()
|
||||
while (leaf != null && !filter(leaf)) {
|
||||
leaf = leaf.prevLeaf()
|
||||
}
|
||||
return leaf
|
||||
}
|
||||
|
||||
public fun PsiElement.nextLeaf(filter: (PsiElement) -> Boolean): PsiElement? {
|
||||
var leaf = nextLeaf()
|
||||
while (leaf != null && !filter(leaf)) {
|
||||
leaf = leaf.nextLeaf()
|
||||
}
|
||||
return leaf
|
||||
}
|
||||
|
||||
public fun PsiElement.getParentOfTypesAndPredicate<T: PsiElement>(
|
||||
strict : Boolean = false, vararg parentClasses : Class<T>, predicate: (T) -> Boolean
|
||||
) : T? {
|
||||
var element = if (strict) getParent() else this
|
||||
while (element != null) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
when {
|
||||
(parentClasses.isEmpty() || parentClasses.any {parentClass -> parentClass.isInstance(element)}) && predicate(element!! as T) ->
|
||||
return element as T
|
||||
element is PsiFile ->
|
||||
return null
|
||||
else ->
|
||||
element = element!!.getParent()
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
public fun PsiElement.getNonStrictParentOfType<T: PsiElement>(parentClass : Class<T>) : T? {
|
||||
return PsiTreeUtil.getParentOfType(this, parentClass, false)
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getParentOfType<reified T: PsiElement>(strict: Boolean): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, javaClass<T>(), strict)
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getStrictParentOfType<reified T: PsiElement>(): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, javaClass<T>(), true)
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getNonStrictParentOfType<reified T: PsiElement>(): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, javaClass<T>(), false)
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getChildOfType<reified T: PsiElement>(): T? {
|
||||
return PsiTreeUtil.getChildOfType(this, javaClass<T>())
|
||||
}
|
||||
|
||||
inline public fun PsiElement.getChildrenOfType<reified T: PsiElement>(): Array<T> {
|
||||
return PsiTreeUtil.getChildrenOfType(this, javaClass<T>()) ?: arrayOf()
|
||||
}
|
||||
|
||||
public fun PsiElement.getNextSiblingIgnoringWhitespaceAndComments(): PsiElement? {
|
||||
return siblings(withItself = false).filter { it !is PsiWhiteSpace && it !is PsiComment }.firstOrNull()
|
||||
}
|
||||
|
||||
public fun PsiElement?.isAncestor(element: PsiElement, strict: Boolean = false): Boolean {
|
||||
return PsiTreeUtil.isAncestor(this, element, strict)
|
||||
}
|
||||
|
||||
public fun <T: PsiElement> T.getIfChildIsInBranch(element: PsiElement, branch: T.() -> PsiElement?): T? {
|
||||
return if (branch().isAncestor(element)) this else null
|
||||
}
|
||||
|
||||
public inline fun PsiElement.getParentOfTypeAndBranch<reified T: PsiElement>(strict: Boolean = false, noinline branch: T.() -> PsiElement?) : T? {
|
||||
return getParentOfType<T>(strict)?.getIfChildIsInBranch(this, branch)
|
||||
}
|
||||
|
||||
public tailRecursive fun PsiElement.getOutermostParentContainedIn(container: PsiElement): PsiElement? {
|
||||
val parent = getParent()
|
||||
return if (parent == container) this else parent?.getOutermostParentContainedIn(container)
|
||||
}
|
||||
|
||||
public fun PsiElement.isInsideOf(elements: Iterable<PsiElement>): Boolean = elements.any { it.isAncestor(this) }
|
||||
|
||||
// -------------------- Recursive tree visiting --------------------------------------------------------------------------------------------
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(noinline action: (T) -> Unit) {
|
||||
forEachDescendantOfType<T>({true}, action)
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.forEachDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline action: (T) -> Unit) {
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (canGoInside(element)) {
|
||||
super.visitElement(element)
|
||||
}
|
||||
|
||||
if (element is T) {
|
||||
action(element)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(noinline predicate: (T) -> Boolean = { true }): Boolean {
|
||||
return findDescendantOfType<T>(predicate) != null
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.anyDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): Boolean {
|
||||
return findDescendantOfType<T>(canGoInside, predicate) != null
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(noinline predicate: (T) -> Boolean = { true }): T? {
|
||||
return findDescendantOfType<T>({ true}, predicate)
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.findDescendantOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): T? {
|
||||
var result: T? = null
|
||||
this.accept(object : PsiRecursiveElementVisitor(){
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (result != null) return
|
||||
|
||||
if (element is T && predicate(element)) {
|
||||
result = element
|
||||
return
|
||||
}
|
||||
|
||||
if (canGoInside(element)) {
|
||||
super.visitElement(element)
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(noinline predicate: (T) -> Boolean = { true }): List<T> {
|
||||
return collectDescendantsOfType<T>({ true }, predicate)
|
||||
}
|
||||
|
||||
public inline fun <reified T : PsiElement> PsiElement.collectDescendantsOfType(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) canGoInside: (PsiElement) -> Boolean, noinline predicate: (T) -> Boolean = { true }): List<T> {
|
||||
val result = ArrayList<T>()
|
||||
forEachDescendantOfType<T>(canGoInside) {
|
||||
if (predicate(it)) {
|
||||
result.add(it)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ----------- Working with offsets, ranges and texts ----------------------------------------------------------------------------------------------
|
||||
|
||||
public val PsiElement.startOffset: Int
|
||||
get() = getTextRange().getStartOffset()
|
||||
@@ -30,50 +209,13 @@ public val PsiElement.endOffset: Int
|
||||
public fun PsiElement.getStartOffsetIn(ancestor: PsiElement): Int {
|
||||
var offset = 0
|
||||
var parent = this
|
||||
while (parent != this) {
|
||||
while (parent != ancestor) {
|
||||
offset += parent.getStartOffsetInParent()
|
||||
parent = parent.getParent()
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
public data class PsiChildRange(public val first: PsiElement?, public val last: PsiElement?) : Sequence<PsiElement> {
|
||||
init {
|
||||
if (first == null) {
|
||||
assert(last == null)
|
||||
}
|
||||
else {
|
||||
assert(first.getParent() == last!!.getParent())
|
||||
}
|
||||
}
|
||||
|
||||
public val isEmpty: Boolean
|
||||
get() = first == null
|
||||
|
||||
override fun iterator(): Iterator<PsiElement> {
|
||||
val sequence = if (first == null) {
|
||||
emptySequence<PsiElement>()
|
||||
}
|
||||
else {
|
||||
val afterLast = last!!.getNextSibling()
|
||||
first.siblings().takeWhile { it != afterLast }
|
||||
}
|
||||
return sequence.iterator()
|
||||
}
|
||||
|
||||
companion object {
|
||||
public val EMPTY: PsiChildRange = PsiChildRange(null, null)
|
||||
|
||||
public fun singleElement(element: PsiElement): PsiChildRange = PsiChildRange(element, element)
|
||||
}
|
||||
}
|
||||
|
||||
public val PsiElement.allChildren: PsiChildRange
|
||||
get() {
|
||||
val first = getFirstChild()
|
||||
return if (first != null) PsiChildRange(first, getLastChild()) else PsiChildRange.EMPTY
|
||||
}
|
||||
|
||||
public val PsiChildRange.textRange: TextRange?
|
||||
get() {
|
||||
if (isEmpty) return null
|
||||
@@ -85,3 +227,62 @@ public fun PsiChildRange.getText(): String {
|
||||
return this.map { it.getText() }.joinToString("")
|
||||
}
|
||||
|
||||
public fun PsiFile.elementsInRange(range: TextRange): List<PsiElement> {
|
||||
var offset = range.getStartOffset()
|
||||
val result = ArrayList<PsiElement>()
|
||||
while (offset < range.getEndOffset()) {
|
||||
val currentRange = TextRange(offset, range.getEndOffset())
|
||||
val leaf = findFirstLeafWhollyInRange(this, currentRange) ?: break
|
||||
|
||||
val element = leaf
|
||||
.parentsWithSelf
|
||||
.first {
|
||||
val parent = it.getParent()
|
||||
it is PsiFile || parent.getTextRange() !in currentRange
|
||||
}
|
||||
result.add(element)
|
||||
|
||||
offset = element.endOffset
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun findFirstLeafWhollyInRange(file: PsiFile, range: TextRange): PsiElement? {
|
||||
var element = file.findElementAt(range.getStartOffset()) ?: return null
|
||||
var elementRange = element.getTextRange()
|
||||
if (elementRange.getStartOffset() < range.getStartOffset()) {
|
||||
element = element.nextLeaf(skipEmptyElements = true) ?: return null
|
||||
elementRange = element.getTextRange()
|
||||
}
|
||||
assert(elementRange.getStartOffset() >= range.getStartOffset())
|
||||
return if (elementRange.getEndOffset() <= range.getEndOffset()) element else null
|
||||
}
|
||||
|
||||
// ---------------------------------- Debug/logging ----------------------------------------------------------------------------------------
|
||||
|
||||
public fun PsiElement.getElementTextWithContext(): String {
|
||||
if (this is PsiFile) {
|
||||
return getContainingFile().getText()
|
||||
}
|
||||
|
||||
// Find parent for element among file children
|
||||
val topLevelElement = PsiTreeUtil.findFirstParent(this, { it.getParent() is PsiFile }) ?:
|
||||
throw AssertionError("For non-file element we should always be able to find parent in file children")
|
||||
|
||||
val startContextOffset = topLevelElement.startOffset
|
||||
val elementContextOffset = getTextRange().getStartOffset()
|
||||
|
||||
val inFileParentOffset = elementContextOffset - startContextOffset
|
||||
|
||||
return StringBuilder(topLevelElement.getText())
|
||||
.insert(inFileParentOffset, "<caret>")
|
||||
.insert(0, "File name: ${getContainingFile().getName()}\n")
|
||||
.toString()
|
||||
}
|
||||
|
||||
public fun PsiElement.getTextWithLocation(): String = "'${this.getText()}' at ${DiagnosticUtils.atLocation(this)}"
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public fun SearchScope.contains(element: PsiElement): Boolean = PsiSearchScopeUtil.isInScope(this, element)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinFileStubImpl;
|
||||
import java.io.IOException;
|
||||
|
||||
public class JetFileElementType extends IStubFileElementType<KotlinFileStub> {
|
||||
public static final int STUB_VERSION = 46;
|
||||
public static final int STUB_VERSION = 47;
|
||||
|
||||
private static final String NAME = "kotlin.FILE";
|
||||
|
||||
|
||||
@@ -105,6 +105,15 @@ public class AnnotationResolver {
|
||||
return resolveAnnotations(scope, modifierList, trace, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Annotations resolveAnnotationsWithoutArguments(
|
||||
@NotNull JetScope scope,
|
||||
@NotNull List<JetAnnotationEntry> annotationEntries,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
return resolveAnnotationEntries(scope, annotationEntries, trace, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Annotations resolveAnnotationsWithArguments(
|
||||
@NotNull JetScope scope,
|
||||
@@ -144,7 +153,7 @@ public class AnnotationResolver {
|
||||
descriptor = new LazyAnnotationDescriptor(new LazyAnnotationsContextImpl(this, storageManager, trace, scope), entryElement);
|
||||
}
|
||||
if (shouldResolveArguments) {
|
||||
resolveAnnotationArguments(entryElement, trace);
|
||||
resolveAnnotationArguments(descriptor);
|
||||
}
|
||||
|
||||
result.add(descriptor);
|
||||
@@ -202,30 +211,13 @@ public class AnnotationResolver {
|
||||
);
|
||||
}
|
||||
|
||||
public static void resolveAnnotationsArguments(@Nullable JetModifierList modifierList, @NotNull BindingTrace trace) {
|
||||
if (modifierList == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
|
||||
resolveAnnotationArguments(annotationEntry, trace);
|
||||
}
|
||||
}
|
||||
|
||||
public static void resolveAnnotationsArguments(@NotNull Annotations annotations, @NotNull BindingTrace trace) {
|
||||
public static void resolveAnnotationsArguments(@NotNull Annotations annotations) {
|
||||
for (AnnotationDescriptor annotationDescriptor : annotations) {
|
||||
JetAnnotationEntry annotationEntry = trace.getBindingContext().get(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT, annotationDescriptor);
|
||||
assert annotationEntry != null : "Cannot find annotation entry: " + annotationDescriptor;
|
||||
resolveAnnotationArguments(annotationEntry, trace);
|
||||
resolveAnnotationArguments(annotationDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private static void resolveAnnotationArguments(
|
||||
@NotNull JetAnnotationEntry annotationEntry,
|
||||
@NotNull BindingTrace trace
|
||||
) {
|
||||
AnnotationDescriptor annotationDescriptor = trace.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry);
|
||||
assert annotationDescriptor != null : "Annotation descriptor should be created before resolving arguments for " + annotationEntry.getText();
|
||||
private static void resolveAnnotationArguments(@NotNull AnnotationDescriptor annotationDescriptor) {
|
||||
if (annotationDescriptor instanceof LazyAnnotationDescriptor) {
|
||||
((LazyAnnotationDescriptor) annotationDescriptor).forceResolveAllContents();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ package org.jetbrains.kotlin.resolve.annotations
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
public fun DeclarationDescriptor.hasInlineAnnotation(): Boolean {
|
||||
@@ -49,3 +51,12 @@ private fun CallableDescriptor.isPlatformStaticIn(predicate: (DeclarationDescrip
|
||||
}
|
||||
else -> predicate(getContainingDeclaration()) && hasPlatformStaticAnnotation()
|
||||
}
|
||||
|
||||
public fun AnnotationDescriptor.argumentValue(parameterName: String): Any? {
|
||||
return getAllValueArguments().entrySet()
|
||||
.singleOrNull { it.key.getName().asString() == parameterName }
|
||||
?.value?.getValue()
|
||||
}
|
||||
|
||||
public fun AnnotationDescriptor.deprecatedAnnotationMessage(): String?
|
||||
= argumentValue("value") as? String
|
||||
|
||||
@@ -159,7 +159,7 @@ public class BodyResolver {
|
||||
@NotNull final ConstructorDescriptor descriptor,
|
||||
@NotNull JetScope declaringScope
|
||||
) {
|
||||
AnnotationResolver.resolveAnnotationsArguments(constructor.getModifierList(), trace);
|
||||
AnnotationResolver.resolveAnnotationsArguments(descriptor.getAnnotations());
|
||||
|
||||
final CallChecker callChecker = new ConstructorHeaderCallChecker(descriptor, additionalCheckerProvider.getCallChecker());
|
||||
resolveFunctionBody(c, trace, constructor, descriptor, declaringScope,
|
||||
@@ -339,9 +339,6 @@ public class BodyResolver {
|
||||
recordSupertype(typeReference, supertype);
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
|
||||
if (classDescriptor != null) {
|
||||
if (classDescriptor.getKind() == ClassKind.INTERFACE) {
|
||||
trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark));
|
||||
}
|
||||
// allow only one delegating constructor
|
||||
if (primaryConstructorDelegationCall[0] == null) {
|
||||
primaryConstructorDelegationCall[0] = results.getResultingCall();
|
||||
@@ -374,6 +371,7 @@ public class BodyResolver {
|
||||
}
|
||||
if (descriptor.getKind() != ClassKind.INTERFACE &&
|
||||
descriptor.getUnsubstitutedPrimaryConstructor() != null &&
|
||||
superClass.getKind() != ClassKind.INTERFACE &&
|
||||
!superClass.getConstructors().isEmpty() &&
|
||||
!ErrorUtils.isError(superClass)
|
||||
) {
|
||||
@@ -429,6 +427,8 @@ public class BodyResolver {
|
||||
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
|
||||
if (classDescriptor != null) {
|
||||
if (ErrorUtils.isError(classDescriptor)) continue;
|
||||
|
||||
if (classDescriptor.getKind() != ClassKind.INTERFACE) {
|
||||
if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
|
||||
trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
|
||||
@@ -501,17 +501,17 @@ public class BodyResolver {
|
||||
|
||||
private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
|
||||
for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
|
||||
if (!(entry.getKey() instanceof JetClass)) continue;
|
||||
JetClass klass = (JetClass) entry.getKey();
|
||||
JetClassOrObject klass = entry.getKey();
|
||||
ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
|
||||
ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
|
||||
AnnotationResolver.resolveAnnotationsArguments(klass.getPrimaryConstructorModifierList(), trace);
|
||||
|
||||
if (unsubstitutedPrimaryConstructor != null) {
|
||||
WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForClassHeaderResolution(), unsubstitutedPrimaryConstructor);
|
||||
valueParameterResolver.resolveValueParameters(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(),
|
||||
parameterScope, c.getOuterDataFlowInfo(), trace);
|
||||
AnnotationResolver.resolveAnnotationsArguments(unsubstitutedPrimaryConstructor.getAnnotations());
|
||||
|
||||
WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForClassHeaderResolution(),
|
||||
unsubstitutedPrimaryConstructor);
|
||||
valueParameterResolver.resolveValueParameters(klass.getPrimaryConstructorParameters(),
|
||||
unsubstitutedPrimaryConstructor.getValueParameters(),
|
||||
parameterScope, c.getOuterDataFlowInfo(), trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -559,7 +559,7 @@ public class BodyResolver {
|
||||
resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberDeclarationResolution(), propertyScope);
|
||||
}
|
||||
|
||||
resolveAnnotationArguments(propertyScope, property);
|
||||
AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations());
|
||||
|
||||
resolvePropertyAccessors(c, property, propertyDescriptor);
|
||||
processed.add(property);
|
||||
@@ -587,7 +587,7 @@ public class BodyResolver {
|
||||
resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
|
||||
}
|
||||
|
||||
resolveAnnotationArguments(propertyScope, property);
|
||||
AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations());
|
||||
|
||||
resolvePropertyAccessors(c, property, propertyDescriptor);
|
||||
}
|
||||
@@ -610,7 +610,7 @@ public class BodyResolver {
|
||||
PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
|
||||
if (getter != null && getterDescriptor != null) {
|
||||
JetScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
|
||||
resolveAnnotationArguments(accessorScope, getter);
|
||||
AnnotationResolver.resolveAnnotationsArguments(getterDescriptor.getAnnotations());
|
||||
resolveFunctionBody(c, fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
|
||||
}
|
||||
|
||||
@@ -618,7 +618,7 @@ public class BodyResolver {
|
||||
PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
|
||||
if (setter != null && setterDescriptor != null) {
|
||||
JetScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
|
||||
resolveAnnotationArguments(accessorScope, setter);
|
||||
AnnotationResolver.resolveAnnotationsArguments(setterDescriptor.getAnnotations());
|
||||
resolveFunctionBody(c, fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
|
||||
}
|
||||
}
|
||||
@@ -778,10 +778,6 @@ public class BodyResolver {
|
||||
c.getOuterDataFlowInfo(), trace);
|
||||
}
|
||||
|
||||
private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) {
|
||||
AnnotationResolver.resolveAnnotationsArguments(owner.getModifierList(), trace);
|
||||
}
|
||||
|
||||
private static void computeDeferredType(JetType type) {
|
||||
// handle type inference loop: function or property body contains a reference to itself
|
||||
// fun f() = { f() }
|
||||
|
||||
@@ -87,6 +87,8 @@ public class DeclarationsChecker {
|
||||
checkObject((JetObjectDeclaration) classOrObject, classDescriptor);
|
||||
}
|
||||
|
||||
checkPrimaryConstructor(classOrObject, classDescriptor);
|
||||
|
||||
modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor);
|
||||
}
|
||||
|
||||
@@ -244,7 +246,6 @@ public class DeclarationsChecker {
|
||||
private void checkClass(BodiesResolveContext c, JetClass aClass, ClassDescriptorWithResolutionScopes classDescriptor) {
|
||||
AnnotationResolver.reportDeprecatedAnnotationSyntax(aClass.getAnnotations(), trace);
|
||||
checkOpenMembers(classDescriptor);
|
||||
checkPrimaryConstructor(aClass, classDescriptor);
|
||||
checkTypeParameters(aClass);
|
||||
|
||||
if (aClass.isInterface()) {
|
||||
@@ -271,9 +272,9 @@ public class DeclarationsChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPrimaryConstructor(JetClass aClass, ClassDescriptor classDescriptor) {
|
||||
private void checkPrimaryConstructor(JetClassOrObject classOrObject, ClassDescriptor classDescriptor) {
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
JetPrimaryConstructor declaration = aClass.getPrimaryConstructor();
|
||||
JetPrimaryConstructor declaration = classOrObject.getPrimaryConstructor();
|
||||
if (primaryConstructor == null || declaration == null) return;
|
||||
|
||||
for (JetParameter parameter : declaration.getValueParameters()) {
|
||||
@@ -287,6 +288,10 @@ public class DeclarationsChecker {
|
||||
trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList()));
|
||||
}
|
||||
|
||||
if (!(classOrObject instanceof JetClass)) {
|
||||
trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration));
|
||||
}
|
||||
|
||||
checkConstructorDeclaration(primaryConstructor, declaration);
|
||||
}
|
||||
|
||||
@@ -303,9 +308,9 @@ public class DeclarationsChecker {
|
||||
}
|
||||
|
||||
private void checkConstructorInTrait(JetClass klass) {
|
||||
JetParameterList primaryConstructorParameterList = klass.getPrimaryConstructorParameterList();
|
||||
if (primaryConstructorParameterList != null) {
|
||||
trace.report(CONSTRUCTOR_IN_TRAIT.on(primaryConstructorParameterList));
|
||||
JetPrimaryConstructor primaryConstructor = klass.getPrimaryConstructor();
|
||||
if (primaryConstructor != null) {
|
||||
trace.report(CONSTRUCTOR_IN_TRAIT.on(primaryConstructor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -351,15 +351,6 @@ public class DescriptorResolver {
|
||||
annotationResolver.resolveAnnotationsWithoutArguments(scope, valueParameter.getModifierList(), trace));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ValueParameterDescriptorImpl resolveValueParameterDescriptorWithAnnotationArguments(
|
||||
JetScope scope, DeclarationDescriptor declarationDescriptor,
|
||||
JetParameter valueParameter, int index, JetType type, BindingTrace trace
|
||||
) {
|
||||
return resolveValueParameterDescriptor(declarationDescriptor, valueParameter, index, type, trace,
|
||||
annotationResolver.resolveAnnotationsWithArguments(scope, valueParameter.getModifierList(), trace));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ValueParameterDescriptorImpl resolveValueParameterDescriptor(
|
||||
DeclarationDescriptor declarationDescriptor,
|
||||
|
||||
@@ -88,7 +88,7 @@ class FunctionDescriptorResolver(
|
||||
): SimpleFunctionDescriptor {
|
||||
val functionDescriptor = functionConstructor(
|
||||
containingDescriptor,
|
||||
annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace),
|
||||
annotationResolver.resolveAnnotationsWithoutArguments(scope, function.getModifierList(), trace),
|
||||
function.getNameAsSafeName(),
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
function.toSourceElement()
|
||||
@@ -147,6 +147,7 @@ class FunctionDescriptorResolver(
|
||||
typeResolver.resolveType(innerScope, receiverTypeRef, trace, true)
|
||||
else
|
||||
expectedFunctionType.getReceiverType()
|
||||
receiverType?.let { AnnotationResolver.resolveAnnotationsArguments(it.getAnnotations()) }
|
||||
|
||||
|
||||
val valueParameterDescriptors = createValueParameterDescriptors(function, functionDescriptor, innerScope, trace, expectedFunctionType)
|
||||
@@ -166,6 +167,9 @@ class FunctionDescriptorResolver(
|
||||
modality,
|
||||
visibility
|
||||
)
|
||||
for (valueParameterDescriptor in valueParameterDescriptors) {
|
||||
AnnotationResolver.resolveAnnotationsArguments(valueParameterDescriptor.getType().getAnnotations())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createValueParameterDescriptors(
|
||||
@@ -210,7 +214,7 @@ class FunctionDescriptorResolver(
|
||||
public fun resolvePrimaryConstructorDescriptor(
|
||||
scope: JetScope,
|
||||
classDescriptor: ClassDescriptor,
|
||||
classElement: JetClass,
|
||||
classElement: JetClassOrObject,
|
||||
trace: BindingTrace
|
||||
): ConstructorDescriptorImpl? {
|
||||
if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY || !classElement.hasPrimaryConstructor()) return null
|
||||
@@ -338,7 +342,7 @@ class FunctionDescriptorResolver(
|
||||
checkConstructorParameterHasNoModifier(trace, valueParameter)
|
||||
}
|
||||
|
||||
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptorWithAnnotationArguments(parameterScope, functionDescriptor,
|
||||
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(parameterScope, functionDescriptor,
|
||||
valueParameter, i, type, trace)
|
||||
parameterScope.addVariableDescriptor(valueParameterDescriptor)
|
||||
result.add(valueParameterDescriptor)
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_TRAIT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.MANY_COMPANION_OBJECTS
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.SECONDARY_CONSTRUCTOR_IN_OBJECT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_OBJECT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -176,7 +176,7 @@ public class LazyTopDownAnalyzer {
|
||||
}
|
||||
else if (jetDeclaration is JetSecondaryConstructor) {
|
||||
if (DescriptorUtils.isSingletonOrAnonymousObject(classDescriptor)) {
|
||||
trace!!.report(SECONDARY_CONSTRUCTOR_IN_OBJECT.on(jetDeclaration))
|
||||
trace!!.report(CONSTRUCTOR_IN_OBJECT.on(jetDeclaration))
|
||||
}
|
||||
else if (classDescriptor.getKind() == ClassKind.INTERFACE) {
|
||||
trace!!.report(CONSTRUCTOR_IN_TRAIT.on(jetDeclaration))
|
||||
@@ -199,10 +199,6 @@ public class LazyTopDownAnalyzer {
|
||||
}
|
||||
|
||||
override fun visitSecondaryConstructor(constructor: JetSecondaryConstructor) {
|
||||
val classDescriptor = lazyDeclarationResolver!!.resolveToDescriptor(constructor.getClassOrObject()) as ClassDescriptor
|
||||
if (!DescriptorUtils.canHaveSecondaryConstructors(classDescriptor)) {
|
||||
return
|
||||
}
|
||||
c.getSecondaryConstructors().put(constructor, lazyDeclarationResolver!!.resolveToDescriptor(constructor) as ConstructorDescriptor)
|
||||
registerScope(c, constructor)
|
||||
}
|
||||
|
||||
@@ -393,12 +393,10 @@ public class ModifiersChecker {
|
||||
|
||||
@NotNull
|
||||
public static Visibility getDefaultClassVisibility(@NotNull ClassDescriptor descriptor) {
|
||||
if (isEnumEntry(descriptor)) {
|
||||
if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) {
|
||||
// should be be accessible where containing class is accessible by default
|
||||
return Visibilities.PUBLIC;
|
||||
}
|
||||
if (isCompanionObject(descriptor)) {
|
||||
return ((ClassDescriptor) descriptor.getContainingDeclaration()).getVisibility();
|
||||
}
|
||||
return Visibilities.INTERNAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public class TypeResolver(
|
||||
|
||||
private fun doResolvePossiblyBareType(c: TypeResolutionContext, typeReference: JetTypeReference): PossiblyBareType {
|
||||
AnnotationResolver.reportDeprecatedAnnotationSyntax(typeReference.getAnnotations(), c.trace);
|
||||
val annotations = annotationResolver.resolveAnnotationsWithArguments(c.scope, typeReference.getAnnotationEntries(), c.trace)
|
||||
val annotations = annotationResolver.resolveAnnotationsWithoutArguments(c.scope, typeReference.getAnnotationEntries(), c.trace)
|
||||
|
||||
val typeElement = typeReference.getTypeElement()
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
@@ -283,7 +283,7 @@ public class ArgumentTypeResolver {
|
||||
// For an unsafe call, we should not do it,
|
||||
// otherwise not-null will propagate to successive statements
|
||||
// Sample: x?.foo(x.bar()) // Inside foo call, x is not-nullable
|
||||
if (PsiUtilPackage.isSafeCall(call)) {
|
||||
if (CallUtilPackage.isSafeCall(call)) {
|
||||
initialDataFlowInfo = initialDataFlowInfo.disequate(receiverDataFlowValue, DataFlowValue.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,9 +349,12 @@ public class CallResolver {
|
||||
Collection<ConstructorDescriptor> constructors = delegateClassDescriptor.getConstructors();
|
||||
|
||||
if (!isThisCall && currentClassDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
|
||||
context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
|
||||
(JetConstructorDelegationCall) calleeExpression.getParent()
|
||||
));
|
||||
if (DescriptorUtils.canHaveDeclaredConstructors(currentClassDescriptor)) {
|
||||
// Diagnostic is meaningless when reporting on interfaces and object
|
||||
context.trace.report(PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(
|
||||
(JetConstructorDelegationCall) calleeExpression.getParent()
|
||||
));
|
||||
}
|
||||
if (call.isImplicit()) return OverloadResolutionResultsImpl.nameNotFound();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl;
|
||||
@@ -637,7 +638,7 @@ public class CandidateResolver {
|
||||
D candidateDescriptor = candidateCall.getCandidateDescriptor();
|
||||
if (TypeUtils.dependsOnTypeParameters(receiverParameter.getType(), candidateDescriptor.getTypeParameters())) return SUCCESS;
|
||||
|
||||
boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && PsiUtilPackage.isExplicitSafeCall(candidateCall.getCall());
|
||||
boolean safeAccess = isExplicitReceiver && !implicitInvokeCheck && CallUtilPackage.isExplicitSafeCall(candidateCall.getCall());
|
||||
boolean isSubtypeBySmartCast = SmartCastUtils.isSubTypeBySmartCastIgnoringNullability(
|
||||
receiverArgument, receiverParameter.getType(), context);
|
||||
if (!isSubtypeBySmartCast) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
@@ -37,6 +38,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.NON_KOTLIN_FUNCTION;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*;
|
||||
|
||||
@@ -150,11 +153,17 @@ public class ValueArgumentsToParametersMapper {
|
||||
public ProcessorState processNamedArgument(@NotNull ValueArgument argument) {
|
||||
assert argument.isNamed();
|
||||
|
||||
D candidate = candidateCall.getCandidateDescriptor();
|
||||
|
||||
JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression();
|
||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName());
|
||||
if (!candidateCall.getCandidateDescriptor().hasStableParameterNames()) {
|
||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(nameReference));
|
||||
if (!candidate.hasStableParameterNames()) {
|
||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||
nameReference,
|
||||
candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION
|
||||
));
|
||||
}
|
||||
|
||||
if (valueParameterDescriptor == null) {
|
||||
report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference));
|
||||
unmappedArguments.add(argument);
|
||||
|
||||
@@ -25,9 +25,9 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.kotlin.psi.Call;
|
||||
import org.jetbrains.kotlin.psi.ValueArgument;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolverUtil;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
|
||||
@@ -288,7 +288,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
|
||||
@Override
|
||||
public boolean isSafeCall() {
|
||||
return PsiUtilPackage.isSafeCall(call);
|
||||
return CallUtilPackage.isSafeCall(call);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -87,7 +87,14 @@ private fun createSynthesizedFunctionWithFirstParameterAsReceiver(descriptor: Fu
|
||||
}
|
||||
|
||||
fun isSynthesizedInvoke(descriptor: DeclarationDescriptor): Boolean {
|
||||
return descriptor.getName() == OperatorConventions.INVOKE &&
|
||||
(descriptor as? FunctionDescriptor)?.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
||||
descriptor.getContainingDeclaration() is FunctionClassDescriptor
|
||||
if (descriptor.getName() != OperatorConventions.INVOKE || descriptor !is FunctionDescriptor) return false
|
||||
|
||||
var real: FunctionDescriptor = descriptor
|
||||
while (!real.getKind().isReal()) {
|
||||
// You can't override two different synthesized invokes at the same time
|
||||
real = real.getOverriddenDescriptors().singleOrNull() ?: return false
|
||||
}
|
||||
|
||||
return real.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
||||
real.getContainingDeclaration() is FunctionClassDescriptor
|
||||
}
|
||||
|
||||
@@ -20,15 +20,16 @@ import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.CALL
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.RESOLVED_CALL
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
// resolved call
|
||||
@@ -176,6 +177,18 @@ public fun JetExpression.getFunctionResolvedCallWithAssert(context: BindingConte
|
||||
assert(resolvedCall.getResultingDescriptor() is FunctionDescriptor) {
|
||||
"ResolvedCall for this expression must be ResolvedCall<? extends FunctionDescriptor>: ${this.getTextWithLocation()}"
|
||||
}
|
||||
[suppress("UNCHECKED_CAST")]
|
||||
@suppress("UNCHECKED_CAST")
|
||||
return resolvedCall as ResolvedCall<out FunctionDescriptor>
|
||||
}
|
||||
|
||||
public fun Call.isSafeCall(): Boolean {
|
||||
if (this is CallTransformer.CallForImplicitInvoke) {
|
||||
//implicit safe 'invoke'
|
||||
if (getOuterCall().isExplicitSafeCall()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return isExplicitSafeCall()
|
||||
}
|
||||
|
||||
public fun Call.isExplicitSafeCall(): Boolean = getCallOperationNode()?.getElementType() == JetTokens.SAFE_ACCESS
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
import org.jetbrains.kotlin.resolve.AnnotationResolver;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
|
||||
@@ -143,7 +144,7 @@ public class LazyDeclarationResolver {
|
||||
public DeclarationDescriptor visitParameter(@NotNull JetParameter parameter, Void data) {
|
||||
PsiElement grandFather = parameter.getParent().getParent();
|
||||
if (grandFather instanceof JetPrimaryConstructor) {
|
||||
JetClass jetClass = ((JetPrimaryConstructor) grandFather).getContainingClass();
|
||||
JetClassOrObject jetClass = ((JetPrimaryConstructor) grandFather).getContainingClassOrObject();
|
||||
// This is a primary constructor parameter
|
||||
ClassDescriptor classDescriptor = getClassDescriptor(jetClass);
|
||||
if (parameter.hasValOrVarNode()) {
|
||||
@@ -183,7 +184,7 @@ public class LazyDeclarationResolver {
|
||||
|
||||
@Override
|
||||
public DeclarationDescriptor visitPrimaryConstructor(@NotNull JetPrimaryConstructor constructor, Void data) {
|
||||
JetClass klass = constructor.getContainingClass();
|
||||
JetClassOrObject klass = constructor.getContainingClassOrObject();
|
||||
getClassDescriptor(klass).getConstructors();
|
||||
return getBindingContext().get(BindingContext.CONSTRUCTOR, klass);
|
||||
}
|
||||
@@ -210,6 +211,7 @@ public class LazyDeclarationResolver {
|
||||
throw new IllegalStateException("No descriptor resolved for " + declaration + ":\n" +
|
||||
PsiUtilPackage.getElementTextWithContext(declaration));
|
||||
}
|
||||
AnnotationResolver.resolveAnnotationsArguments(result.getAnnotations());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,9 @@ class AliasImportsIndexed(allImports: Collection<JetImportDirective>) : IndexedI
|
||||
val builder = ImmutableListMultimap.builder<Name, JetImportDirective>()
|
||||
|
||||
for (directive in imports) {
|
||||
val path = directive.getImportPath() ?: continue // can be some parse errors
|
||||
builder.put(path.getImportedName()!!, directive)
|
||||
val path = directive.getImportPath() ?: continue // parse error
|
||||
val importedName = path.getImportedName() ?: continue // parse error
|
||||
builder.put(importedName, directive)
|
||||
}
|
||||
|
||||
builder.build()
|
||||
|
||||
@@ -51,12 +51,6 @@ public class JetClassInfo extends JetClassOrObjectInfo<JetClass> {
|
||||
return element.getTypeParameterList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends JetParameter> getPrimaryConstructorParameters() {
|
||||
return element.getPrimaryConstructorParameters();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassKind getClassKind() {
|
||||
|
||||
@@ -90,6 +90,12 @@ public abstract class JetClassOrObjectInfo<E extends JetClassOrObject> implement
|
||||
return body == null ? Collections.<JetAnnotationEntry>emptyList() : body.getDanglingAnnotations();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends JetParameter> getPrimaryConstructorParameters() {
|
||||
return element.getPrimaryConstructorParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "info for " + element.getText();
|
||||
|
||||
@@ -42,12 +42,6 @@ public class JetObjectInfo extends JetClassOrObjectInfo<JetObjectDeclaration> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends JetParameter> getPrimaryConstructorParameters() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassKind getClassKind() {
|
||||
|
||||
@@ -101,7 +101,6 @@ public abstract class AbstractLazyMemberScope<D : DeclarationDescriptor, DP : De
|
||||
trace,
|
||||
c.scopeProvider.getOuterDataFlowInfoForDeclaration(propertyDeclaration))
|
||||
result.add(propertyDescriptor)
|
||||
AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations(), trace)
|
||||
}
|
||||
|
||||
getNonDeclaredProperties(name, result)
|
||||
|
||||
@@ -134,8 +134,7 @@ public open class LazyClassMemberScope(
|
||||
private fun generateDataClassMethods(result: MutableCollection<FunctionDescriptor>, name: Name) {
|
||||
if (!KotlinBuiltIns.isData(thisDescriptor)) return
|
||||
|
||||
val constructor = getPrimaryConstructor()
|
||||
if (constructor == null) return
|
||||
val constructor = getPrimaryConstructor() ?: return
|
||||
|
||||
val primaryConstructorParameters = declarationProvider.getOwnerInfo().getPrimaryConstructorParameters()
|
||||
assert(constructor.getValueParameters().size() == primaryConstructorParameters.size()) { "From descriptor: " + constructor.getValueParameters().size() + " but from PSI: " + primaryConstructorParameters.size() }
|
||||
@@ -150,8 +149,6 @@ public open class LazyClassMemberScope(
|
||||
val properties = getProperties(parameter.getName())
|
||||
if (properties.isEmpty()) continue
|
||||
|
||||
assert(properties.size() == 1) { "A constructor parameter is resolved to more than one (" + properties.size() + ") property: " + parameter }
|
||||
|
||||
val property = properties.iterator().next() as PropertyDescriptor
|
||||
|
||||
++componentIndex
|
||||
@@ -275,15 +272,12 @@ public open class LazyClassMemberScope(
|
||||
|
||||
protected open fun resolvePrimaryConstructor(): ConstructorDescriptor? {
|
||||
val ownerInfo = declarationProvider.getOwnerInfo()
|
||||
val classOrObject = ownerInfo.getCorrespondingClassOrObject()
|
||||
if (!thisDescriptor.getKind().isSingleton() && !classOrObject.isObjectLiteral()) {
|
||||
assert(classOrObject is JetClass) { "No JetClass for $thisDescriptor" }
|
||||
classOrObject as JetClass
|
||||
val classOrObject = ownerInfo.getCorrespondingClassOrObject() ?: return null
|
||||
|
||||
if (DescriptorUtils.isTrait(thisDescriptor) && declarationProvider.getOwnerInfo().getPrimaryConstructorParameters().isEmpty()) {
|
||||
return null
|
||||
}
|
||||
val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor()
|
||||
if (DescriptorUtils.isTrait(thisDescriptor) && !hasPrimaryConstructor) return null
|
||||
|
||||
if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) {
|
||||
val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor(
|
||||
thisDescriptor.getScopeForClassHeaderResolution(), thisDescriptor, classOrObject, trace)
|
||||
constructor ?: return null
|
||||
@@ -298,10 +292,7 @@ public open class LazyClassMemberScope(
|
||||
}
|
||||
|
||||
private fun resolveSecondaryConstructors(): Collection<ConstructorDescriptor> {
|
||||
val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject()
|
||||
if (!DescriptorUtils.canHaveSecondaryConstructors(thisDescriptor)) return emptyList()
|
||||
// Script classes have usual class descriptors but do not have conventional class body
|
||||
if (classOrObject !is JetClass) return emptyList()
|
||||
val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject() ?: return emptyList()
|
||||
|
||||
return classOrObject.getSecondaryConstructors().map { constructor ->
|
||||
val descriptor = c.functionDescriptorResolver.resolveSecondaryConstructorDescriptor(
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||
import org.jetbrains.kotlin.resolve.annotations.deprecatedAnnotationMessage
|
||||
|
||||
public class DeprecatedSymbolValidator : SymbolUsageValidator {
|
||||
private val JAVA_DEPRECATED = FqName(javaClass<Deprecated>().getName())
|
||||
@@ -89,28 +91,13 @@ public class DeprecatedSymbolValidator : SymbolUsageValidator {
|
||||
}
|
||||
|
||||
private fun createDeprecationDiagnostic(element: PsiElement, descriptor: DeclarationDescriptor, deprecated: AnnotationDescriptor): Diagnostic {
|
||||
val message = getMessageFromAnnotationDescriptor(deprecated)
|
||||
val message = deprecated.deprecatedAnnotationMessage()
|
||||
return if (message == null)
|
||||
Errors.DEPRECATED_SYMBOL.on(element, descriptor)
|
||||
else
|
||||
Errors.DEPRECATED_SYMBOL_WITH_MESSAGE.on(element, descriptor, message)
|
||||
}
|
||||
|
||||
private fun getMessageFromAnnotationDescriptor(descriptor: AnnotationDescriptor): String? {
|
||||
val parameterName = Name.identifier("value")
|
||||
for ((parameterDescriptor, argument) in descriptor.getAllValueArguments()) {
|
||||
if (parameterDescriptor.getName() == parameterName) {
|
||||
val parameterValue = argument.getValue()
|
||||
if (parameterValue is String) {
|
||||
return parameterValue
|
||||
}
|
||||
else
|
||||
return null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private val PROPERTY_SET_OPERATIONS = TokenSet.create(JetTokens.EQ, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS)
|
||||
fun propertyGetterWorkaround(propertyDescriptor: PropertyDescriptor, trace: BindingTrace, expression: PsiElement) {
|
||||
// property getters do not come as callable yet, so we analyse surroundings to check for deprecation annotation on getter
|
||||
|
||||
@@ -136,6 +136,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
|
||||
VariableDescriptor propertyDescriptor = components.descriptorResolver.
|
||||
resolveLocalVariableDescriptor(scope, property, context.dataFlowInfo, context.trace);
|
||||
AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getType().getAnnotations());
|
||||
JetExpression initializer = property.getInitializer();
|
||||
JetTypeInfo typeInfo;
|
||||
if (initializer != null) {
|
||||
|
||||
@@ -90,6 +90,7 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
||||
context.trace, context.dataFlowInfo, context.expectedType
|
||||
)
|
||||
}
|
||||
AnnotationResolver.resolveAnnotationsArguments(functionDescriptor.getAnnotations());
|
||||
|
||||
val functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace)
|
||||
components.expressionTypingServices.checkFunctionReturnType(
|
||||
@@ -165,6 +166,9 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
|
||||
components.functionDescriptorResolver.
|
||||
initializeFunctionDescriptorAndExplicitReturnType(context.scope.getContainingDeclaration(), context.scope, functionLiteral,
|
||||
functionDescriptor, context.trace, context.expectedType)
|
||||
for (parameterDescriptor in functionDescriptor.getValueParameters()) {
|
||||
AnnotationResolver.resolveAnnotationsArguments(parameterDescriptor.getAnnotations())
|
||||
}
|
||||
BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor)
|
||||
return functionDescriptor
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ValueParameterResolver(
|
||||
context: ExpressionTypingContext
|
||||
) {
|
||||
for ((descriptor, parameter) in valueParameterDescriptors zip valueParameters) {
|
||||
AnnotationResolver.resolveAnnotationsArguments(parameter.getModifierList(), context.trace)
|
||||
AnnotationResolver.resolveAnnotationsArguments(descriptor.getAnnotations())
|
||||
resolveDefaultValue(descriptor, parameter, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public class KotlinCodeBlockModificationListener(modificationTracker: PsiModific
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isInsideCodeBlock(element: PsiElement?): Boolean {
|
||||
public fun isInsideCodeBlock(element: PsiElement?): Boolean {
|
||||
if (element is PsiFileSystemItem) return false
|
||||
if (element == null || element.getParent() == null) return true
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ public class LightClassUtil {
|
||||
@Nullable
|
||||
private static PsiClass getWrappingClass(@NotNull JetDeclaration declaration) {
|
||||
if (declaration instanceof JetParameter) {
|
||||
JetClass constructorClass = JetPsiUtil.getClassIfParameterIsProperty((JetParameter) declaration);
|
||||
JetClassOrObject constructorClass = JetPsiUtil.getClassIfParameterIsProperty((JetParameter) declaration);
|
||||
if (constructorClass != null) {
|
||||
return getPsiClass(constructorClass);
|
||||
}
|
||||
|
||||
@@ -17,22 +17,24 @@
|
||||
package org.jetbrains.kotlin.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import java.util.Collections
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
|
||||
public fun JetClassOrObject.toLightClass(): KotlinLightClass? = LightClassUtil.getPsiClass(this) as KotlinLightClass?
|
||||
|
||||
public fun JetDeclaration.toLightElements(): List<PsiNamedElement> =
|
||||
when (this) {
|
||||
is JetClassOrObject -> Collections.singletonList(LightClassUtil.getPsiClass(this))
|
||||
is JetClassOrObject -> LightClassUtil.getPsiClass(this).singletonOrEmptyList()
|
||||
is JetNamedFunction,
|
||||
is JetSecondaryConstructor -> Collections.singletonList(LightClassUtil.getLightClassMethod(this as JetFunction))
|
||||
is JetSecondaryConstructor -> LightClassUtil.getLightClassMethod(this as JetFunction).singletonOrEmptyList()
|
||||
is JetProperty -> LightClassUtil.getLightClassPropertyMethods(this).toList()
|
||||
is JetPropertyAccessor -> Collections.singletonList(LightClassUtil.getLightClassAccessorMethod(this))
|
||||
is JetPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(this).singletonOrEmptyList()
|
||||
is JetParameter -> ArrayList<PsiNamedElement>().let { elements ->
|
||||
toPsiParameter()?.let { psiParameter -> elements.add(psiParameter) }
|
||||
LightClassUtil.getLightClassPropertyMethods(this).toCollection(elements)
|
||||
@@ -49,8 +51,8 @@ public fun PsiElement.toLightMethods(): List<PsiMethod> =
|
||||
is JetProperty -> LightClassUtil.getLightClassPropertyMethods(this).toList()
|
||||
is JetParameter -> LightClassUtil.getLightClassPropertyMethods(this).toList()
|
||||
is JetPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(this).singletonOrEmptyList()
|
||||
is JetClass -> Collections.singletonList(LightClassUtil.getPsiClass(this).getConstructors()[0])
|
||||
is PsiMethod -> Collections.singletonList(this)
|
||||
is JetClass -> LightClassUtil.getPsiClass(this)?.getConstructors()?.first().singletonOrEmptyList()
|
||||
is PsiMethod -> this.singletonList()
|
||||
else -> listOf()
|
||||
}
|
||||
|
||||
@@ -70,12 +72,12 @@ public fun JetParameter.toPsiParameter(): PsiParameter? {
|
||||
|
||||
val paramIndex = paramList.getParameters().indexOf(this)
|
||||
val owner = paramList.getParent()
|
||||
val lightParamIndex = if (owner != null && owner.isExtensionDeclaration()) paramIndex + 1 else paramIndex
|
||||
val lightParamIndex = if (owner is JetDeclaration && owner.isExtensionDeclaration()) paramIndex + 1 else paramIndex
|
||||
|
||||
val method: PsiMethod? = when (owner) {
|
||||
is JetFunction -> LightClassUtil.getLightClassMethod(owner)
|
||||
is JetPropertyAccessor -> LightClassUtil.getLightClassAccessorMethod(owner)
|
||||
is JetPrimaryConstructor -> LightClassUtil.getPsiClass(owner.getContainingClass())?.getConstructors()?.let { constructors ->
|
||||
is JetPrimaryConstructor -> LightClassUtil.getPsiClass(owner.getContainingClassOrObject())?.getConstructors()?.let { constructors ->
|
||||
if (constructors.isNotEmpty()) constructors[0] else null
|
||||
}
|
||||
else -> null
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
class A {
|
||||
fun foo() {
|
||||
try {
|
||||
val a = 1
|
||||
var a = 1
|
||||
a++
|
||||
}
|
||||
catch(e : Throwable) {
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ class A {
|
||||
fun foo() {
|
||||
inlineFun ({
|
||||
var zzz = it;
|
||||
zzz++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ class A {
|
||||
fun foo() {
|
||||
inlineFun ({ l ->
|
||||
var zzz = l;
|
||||
zzz++
|
||||
}, 11)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ class A {
|
||||
var s = 1;
|
||||
inlineFun ({
|
||||
var zzz = 2;
|
||||
zzz++
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ class A {
|
||||
var s = 0;
|
||||
inlineFun {
|
||||
var z = 1;
|
||||
z++
|
||||
|
||||
inlineFun {
|
||||
var zz2 = 2;
|
||||
zz2++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
fun box(): String {
|
||||
try {
|
||||
return "OK"
|
||||
if (1 == 1) {
|
||||
val z = 2
|
||||
}
|
||||
if (3 == 3) {
|
||||
val z = 4
|
||||
}
|
||||
} finally {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fun box(): String {
|
||||
try {
|
||||
return "OK"
|
||||
} finally {
|
||||
if (1 == 1) {
|
||||
val z = 2
|
||||
}
|
||||
if (3 == 3) {
|
||||
val z = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ internal final class A {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
internal companion object Companion {
|
||||
public companion object Companion {
|
||||
private constructor Companion()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
@@ -9,7 +9,7 @@ internal final class A {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
internal companion object Companion : B {
|
||||
public companion object Companion : B {
|
||||
private constructor Companion()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
@@ -14,7 +14,7 @@ internal final class A {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
internal companion object Companion {
|
||||
public companion object Companion {
|
||||
private constructor Companion()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
@@ -14,7 +14,7 @@ internal final class A {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
internal companion object Companion {
|
||||
public companion object Companion {
|
||||
private constructor Companion()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
@@ -6,14 +6,17 @@ enum class Game {
|
||||
companion object {
|
||||
fun foo() = ROCK
|
||||
val bar = PAPER
|
||||
val values2 = values()
|
||||
val scissors = valueOf("SCISSORS")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if (Game.foo() != Game.ROCK) return "Fail 1"
|
||||
// TODO: fix initialization order and uncomment (KT-5761)
|
||||
// if (Game.bar != Game.PAPER) return "Fail 2: ${Game.bar}"
|
||||
if (Game.bar != Game.PAPER) return "Fail 2: ${Game.bar}"
|
||||
if (Game.values().size() != 3) return "Fail 3"
|
||||
if (Game.valueOf("SCISSORS") != Game.SCISSORS) return "Fail 4"
|
||||
if (Game.values2.size() != 3) return "Fail 5"
|
||||
if (Game.scissors != Game.SCISSORS) return "Fail 6"
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,43 +1,36 @@
|
||||
import java.lang.annotation.*
|
||||
import kotlin.reflect.jvm.java
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
Retention(RetentionPolicy.RUNTIME)
|
||||
annotation class Ann(val x: Int)
|
||||
class A {
|
||||
Ann(1) fun foo(Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) {}
|
||||
Ann(1) fun foo(x: Int, y: Int = 2, z: Int) {}
|
||||
|
||||
Ann(1) constructor(Ann(2) x: Int, y: Int = 2, Ann(3) z: Int)
|
||||
Ann(1) constructor(x: Int, y: Int = 2, z: Int)
|
||||
}
|
||||
|
||||
class B [Ann(1)] (Ann(2) x: Int, y: Int = 2, Ann(3) z: Int) {}
|
||||
class B @Ann(1) constructor(x: Int, y: Int = 2, z: Int) {}
|
||||
|
||||
fun Array<out Annotation>.ann() = filterIsInstance<Ann>()
|
||||
|
||||
fun test(name: String, annotations: Array<out Annotation>, parameters: Array<out Array<out Annotation>>) {
|
||||
assertEquals(1, annotations.ann()[0].x, "$name[0]")
|
||||
|
||||
assertEquals(2, parameters[0].ann()[0].x, "$name-param[0]")
|
||||
assertEquals(0, parameters[1].ann().size(), "$name-param[1]")
|
||||
assertEquals(3, parameters[2].ann()[0].x, "$name-param[2]")
|
||||
fun test(name: String, annotations: Array<out Annotation>) {
|
||||
assertEquals(1, annotations.filterIsInstance<Ann>().single().x, "$name[0]")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo = javaClass<A>().getDeclaredMethods().first { it.getName() == "foo" }
|
||||
test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations())
|
||||
test("foo", foo.getDeclaredAnnotations())
|
||||
|
||||
val fooDefault = javaClass<A>().getDeclaredMethods().first { it.getName() == "foo\$default" }
|
||||
test("foo", foo.getDeclaredAnnotations(), foo.getParameterAnnotations())
|
||||
test("foo", foo.getDeclaredAnnotations())
|
||||
|
||||
val (secondary, secondaryDefault) = javaClass<A>().getDeclaredConstructors().partition { it.getParameterTypes().size() == 3 }
|
||||
|
||||
test("secondary", secondary[0].getDeclaredAnnotations(), secondary[0].getParameterAnnotations())
|
||||
test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations(), secondaryDefault[0].getParameterAnnotations())
|
||||
test("secondary", secondary[0].getDeclaredAnnotations())
|
||||
test("secondary\$default", secondaryDefault[0].getDeclaredAnnotations())
|
||||
|
||||
val (primary, primaryDefault) = javaClass<B>().getConstructors().partition { it.getParameterTypes().size() == 3 }
|
||||
|
||||
test("primary", primary[0].getDeclaredAnnotations(), primary[0].getParameterAnnotations())
|
||||
test("secondary\$default", primaryDefault[0].getDeclaredAnnotations(), primaryDefault[0].getParameterAnnotations())
|
||||
test("primary", primary[0].getDeclaredAnnotations())
|
||||
test("primary\$default", primaryDefault[0].getDeclaredAnnotations())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fun box(): String {
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package test
|
||||
|
||||
public/*package*/ open class ClassObject {
|
||||
public/*package*/ constructor ClassObject()
|
||||
public/*package*/ open fun accessToClassObject(): kotlin.Unit
|
||||
public/*package*/ open fun accessToInnerClass(): kotlin.Unit
|
||||
public/*package*/ open fun accessToPackageObject(): kotlin.Unit
|
||||
}
|
||||
|
||||
internal object PackageInner {
|
||||
private constructor PackageInner()
|
||||
internal final val value: kotlin.Int
|
||||
internal final fun foo(): kotlin.Unit
|
||||
}
|
||||
|
||||
internal final class WithClassObject {
|
||||
public constructor WithClassObject()
|
||||
|
||||
public companion object Companion {
|
||||
private constructor Companion()
|
||||
internal final val value: kotlin.Int
|
||||
internal final val valueWithGetter: kotlin.Int
|
||||
internal final var variable: kotlin.Int
|
||||
internal final var variableWithAccessors: kotlin.Int
|
||||
internal final fun foo(): kotlin.Unit
|
||||
}
|
||||
|
||||
internal final class MyInner {
|
||||
public constructor MyInner()
|
||||
internal final val value: kotlin.Int
|
||||
internal final fun foo(): kotlin.Unit
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user